diff options
214 files changed, 10318 insertions, 6993 deletions
diff --git a/.classpath b/.classpath index 381f0d280d..c6230a2c55 100644 --- a/.classpath +++ b/.classpath @@ -11,7 +11,6 @@ <classpathentry kind="src" path="uitest/src"/> <classpathentry kind="src" path="buildhelpers/src"/> <classpathentry kind="src" path="shared/src"/> - <classpathentry kind="src" path="push/src"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"> <attributes> <attribute name="owner.project.facets" value="java"/> @@ -23,11 +23,12 @@ Start Eclipse ------------- Start Eclipse and use the root checkout folder (the one containing the *vaadin*, *gwt* and *gwt-tools* folders) as the workspace folder -Define Required Variables for the GWT Eclipse Projects +Set up the Workspace and define required variables for projects -------- -To be able to find all files, the GWT project requires you to define a couple of variables: - 1. Open *Window* -> *Preferences* (Windows) or *Eclipse* -> *Preferences* (Mac) +1. Go to *General* -> *Workspace* + 1. Set *Text file encoding* to *UTF-8* + 1. Set *New text file line delimiter* to *Unix* 1. Go to *General* -> *Workspace* -> *Linked Resources* 1. Add a new Path Variable **GWT_ROOT** referring to the gwt folder containing the gwt project ![GWT_ROOT](http://f.cl.ly/items/430q0H0z3t362Z1A1n3L/LinkedResources.png "Defining GWT_ROOT") @@ -38,6 +39,15 @@ To be able to find all files, the GWT project requires you to define a couple of ![GWT_TOOLS](http://f.cl.ly/items/1k2Z1n2v0p0y3l0X0D1G/ClasspathVars.png "Defining GWT_TOOLS") 1. Go to Java -> Compiler 1. Check that the compliance level has been set to 1.6 (or higher) +1. Go to XML -> XML Files -> Editor + 1. Ensure the settings are follows: +<pre><code>Line width: 72 +Format comments: true +Join lines: true +Insert whitespace before closing empty end-tags: true +Indent-using spaces: true +Indentation size: 4 +</code></pre> Import the Projects into the Workspace ------------ diff --git a/WebContent/VAADIN/jquery.atmosphere.js b/WebContent/VAADIN/jquery.atmosphere.js index e9def6ae95..2b176668c1 100644 --- a/WebContent/VAADIN/jquery.atmosphere.js +++ b/WebContent/VAADIN/jquery.atmosphere.js @@ -49,7 +49,7 @@ jQuery.atmosphere = function() { }; return { - version : "1.0.12", + version : "1.0.13", requests : [], callbacks : [], @@ -138,13 +138,16 @@ jQuery.atmosphere = function() { */ var _response = { status: 200, + reasonPhrase : "OK", responseBody : '', + messages : [], headers : [], state : "messageReceived", transport : "polling", error: null, request : null, partialMessage : "", + errorHandled: false, id : 0 }; @@ -682,19 +685,21 @@ jQuery.atmosphere = function() { _close(); }; - _response.request = request; - var prevState = _response.state; - _response.state = state; - _response.status = 200; - var prevTransport = _response.transport; - _response.transport = transport; + if (_response.error == null) { + _response.request = request; + var prevState = _response.state; + _response.state = state; + _response.status = 200; + var prevTransport = _response.transport; + _response.transport = transport; - var _body = _response.responseBody; - _invokeCallback(); - _response.responseBody = _body; + var _body = _response.responseBody; + _invokeCallback(); + _response.responseBody = _body; - _response.state = prevState; - _response.transport = prevTransport; + _response.state = prevState; + _response.transport = prevTransport; + } } /** @@ -729,41 +734,43 @@ jQuery.atmosphere = function() { type : rq.method, dataType: "jsonp", error : function(jqXHR, textStatus, errorThrown) { - if (jqXHR.status < 300) { + _response.error = true; + if (jqXHR.status < 300 && rq.reconnect && _requestCount++ < rq.maxReconnectOnClose) { _reconnect(_jqxhr, rq); } else { - _prepareCallback(textStatus, "error", jqXHR.status, rq.transport); + _onError(jqXHR.status, errorThrown); } }, jsonp : "jsonpTransport", success: function(json) { + if (rq.reconnect) { + if (rq.maxRequest == -1 || rq.requestCount++ < rq.maxRequest) { + _readHeaders(_jqxhr, rq); - if (rq.reconnect && (rq.maxRequest == -1 || rq.requestCount++ < rq.maxRequest)) { - _readHeaders(_jqxhr, rq); - - if (!rq.executeCallbackBeforeReconnect) { - _reconnect(_jqxhr, rq); - } + if (!rq.executeCallbackBeforeReconnect) { + _reconnect(_jqxhr, rq); + } - var msg = json.message; - if (msg != null && typeof msg != 'string') { - try { - msg = jQuery.stringifyJSON(msg); - } catch (err) { - // The message was partial + var msg = json.message; + if (msg != null && typeof msg != 'string') { + try { + msg = jQuery.stringifyJSON(msg); + } catch (err) { + // The message was partial + } } - } - if (_handleProtocol(rq, msg)) { - _prepareCallback(msg, "messageReceived", 200, rq.transport); - } + if (_handleProtocol(rq, msg)) { + _prepareCallback(msg, "messageReceived", 200, rq.transport); + } - if (rq.executeCallbackBeforeReconnect) { - _reconnect(_jqxhr, rq); + if (rq.executeCallbackBeforeReconnect) { + _reconnect(_jqxhr, rq); + } + } else { + jQuery.atmosphere.log(_request.logLevel, ["JSONP reconnect maximum try reached " + _request.requestCount]); + _onError(0, "maxRequest reached"); } - } else { - jQuery.atmosphere.log(_request.logLevel, ["JSONP reconnect maximum try reached " + _request.requestCount]); - _onError(); } }, data : rq.data, @@ -802,29 +809,32 @@ jQuery.atmosphere = function() { url : url, type : rq.method, error : function(jqXHR, textStatus, errorThrown) { + _response.error = true; if (jqXHR.status < 300) { _reconnect(_jqxhr, rq); } else { - _prepareCallback(textStatus, "error", jqXHR.status, rq.transport); + _onError(jqXHR.status, errorThrown); } }, success: function(data, textStatus, jqXHR) { - if (rq.reconnect && (rq.maxRequest == -1 || rq.requestCount++ < rq.maxRequest)) { - if (!rq.executeCallbackBeforeReconnect) { - _reconnect(_jqxhr, rq); - } + if (rq.reconnect) { + if (rq.maxRequest == -1 || rq.requestCount++ < rq.maxRequest) { + if (!rq.executeCallbackBeforeReconnect) { + _reconnect(_jqxhr, rq); + } - if (_handleProtocol(rq, data)) { - _prepareCallback(data, "messageReceived", 200, rq.transport); - } + if (_handleProtocol(rq, data)) { + _prepareCallback(data, "messageReceived", 200, rq.transport); + } - if (rq.executeCallbackBeforeReconnect) { - _reconnect(_jqxhr, rq); + if (rq.executeCallbackBeforeReconnect) { + _reconnect(_jqxhr, rq); + } + } else { + jQuery.atmosphere.log(_request.logLevel, ["AJAX reconnect maximum try reached " + _request.requestCount]); + _onError(0, "maxRequest reached"); } - } else { - jQuery.atmosphere.log(_request.logLevel, ["AJAX reconnect maximum try reached " + _request.requestCount]); - _onError(); } }, beforeSend : function(jqXHR) { @@ -912,7 +922,14 @@ jQuery.atmosphere = function() { } return; } - _sse = new EventSource(location, {withCredentials: _request.withCredentials}); + + try { + _sse = new EventSource(location, {withCredentials: _request.withCredentials}); + } catch (e) { + _onError(0, e); + _reconnectWithFallbackTransport("SSE failed. Downgrading to fallback transport and resending"); + return; + } if (_request.connectTimeout > 0) { _request.id = setTimeout(function() { @@ -944,31 +961,25 @@ jQuery.atmosphere = function() { return; } - if (!_handleProtocol(_request, message.data)) return; + var data = message.data; + + if (!_handleProtocol(_request, data)) return; _response.state = 'messageReceived'; _response.status = 200; - var message = message.data; - var skipCallbackInvocation = _trackMessageSize(message, _request, _response); - - if (jQuery.trim(message).length == 0) { - skipCallbackInvocation = true; - } - + var skipCallbackInvocation = _trackMessageSize(data, _request, _response); if (!skipCallbackInvocation) { _invokeCallback(); _response.responseBody = ''; + _response.messages = []; } }; _sse.onerror = function(message) { clearTimeout(_request.id); - _response.state = 'closed'; - _response.responseBody = ""; - _response.status = !sseOpened ? 501 : 200; - _invokeCallback(); + _invokeClose(sseOpened); _clearState(); if (_abordingConnection) { @@ -981,9 +992,10 @@ jQuery.atmosphere = function() { _executeSSE(true); }, _request.reconnectInterval); _response.responseBody = ""; + _response.messages = []; } else { jQuery.atmosphere.log(_request.logLevel, ["SSE reconnect maximum try reached " + _requestCount]); - _onError(); + _onError(0, "maxReconnectOnClose reached"); } } }; @@ -1025,7 +1037,6 @@ jQuery.atmosphere = function() { } _websocket = _getWebSocket(location); - if (_request.connectTimeout > 0) { _request.id = setTimeout(function() { if (!webSocketOpened) { @@ -1062,6 +1073,7 @@ jQuery.atmosphere = function() { } webSocketOpened = true; + _websocket.webSocketOpened = webSocketOpened; if (_request.method == 'POST') { _response.state = "messageReceived"; @@ -1078,17 +1090,18 @@ jQuery.atmosphere = function() { }, _request.reconnectInterval) }, _request.timeout); - if (!_handleProtocol(_request, message.data)) return; + var data = message.data; + + if (!_handleProtocol(_request, data)) return; _response.state = 'messageReceived'; _response.status = 200; - var message = message.data; - var skipCallbackInvocation = _trackMessageSize(message, _request, _response); - + var skipCallbackInvocation = _trackMessageSize(data, _request, _response); if (!skipCallbackInvocation) { _invokeCallback(); _response.responseBody = ''; + _response.messages = []; } }; @@ -1098,6 +1111,7 @@ jQuery.atmosphere = function() { _websocket.onclose = function(message) { if (closed) return + clearTimeout(_request.id); var reason = message.reason; if (reason === "") { @@ -1133,12 +1147,7 @@ jQuery.atmosphere = function() { jQuery.atmosphere.warn("Websocket closed, reason: " + reason); jQuery.atmosphere.warn("Websocket closed, wasClean: " + message.wasClean); - _response.state = 'closed'; - _response.responseBody = ""; - _response.status = !webSocketOpened ? 501 : 200; - _invokeCallback(); - clearTimeout(_request.id); - + _invokeClose(webSocketOpened); closed = true; if (_abordingConnection) { @@ -1151,12 +1160,13 @@ jQuery.atmosphere = function() { if (_request.reconnect && _requestCount++ < _request.maxReconnectOnClose) { _request.id = setTimeout(function() { _response.responseBody = ""; + _response.messages = []; _executeWebSocket(true); }, _request.reconnectInterval); } else { jQuery.atmosphere.log(_request.logLevel, ["Websocket reconnect maximum try reached " + _requestCount]); jQuery.atmosphere.warn("Websocket error, reason: " + message.reason); - _onError(); + _onError(0, "maxReconnectOnClose reached"); } } }; @@ -1164,22 +1174,25 @@ jQuery.atmosphere = function() { function _handleProtocol(request, message) { // The first messages is always the uuid. - if (request.enableProtocol && request.firstMessage) { + if (jQuery.trim(message) != 0 && request.enableProtocol && request.firstMessage) { request.firstMessage = false; var messages = message.split(request.messageDelimiter); - request.uuid = messages[0]; - request.stime = messages[1]; + var pos = messages.length == 2 ? 0 : 1; + request.uuid = jQuery.trim(messages[pos]); + request.stime = jQuery.trim(messages[pos + 1]); return false; } return true; } - function _onError() { + function _onError(code, reason) { _clearState(); _response.state = 'error'; + _response.reasonPhrase = reason; _response.responseBody = ""; - _response.status = 500; + _response.messages = []; + _response.status = code; _invokeCallback(); } @@ -1203,7 +1216,7 @@ jQuery.atmosphere = function() { var messageLength = 0; var messageStart = message.indexOf(request.messageDelimiter); while (messageStart != -1) { - messageLength = message.substring(messageLength, messageStart); + messageLength = jQuery.trim(message.substring(messageLength, messageStart)); message = message.substring(messageStart + request.messageDelimiter.length, message.length); if (message.length == 0 || message.length < messageLength) break; @@ -1220,8 +1233,11 @@ jQuery.atmosphere = function() { if (messages.length != 0) { response.responseBody = messages.join(request.messageDelimiter); + response.messages = messages; return false; } else { + response.responseBody = ""; + response.messages = []; return true; } } else { @@ -1246,15 +1262,16 @@ jQuery.atmosphere = function() { } _request.transport = _request.fallbackTransport; - var reconnect = _request.reconnect && _requestCount++ < _request.maxReconnectOnClose; - if (reconnect && _request.transport != 'none' || _request.transport == null) { + var reconnectInterval = _request.connectTimeout == -1 ? 0 : _request.connectTimeout; + if (_request.reconnect && _request.transport != 'none' || _request.transport == null) { _request.method = _request.fallbackMethod; _response.transport = _request.fallbackTransport; + _request.fallbackTransport = 'none'; _request.id = setTimeout(function() { _execute(); - }, _request.reconnectInterval); - } else if (!reconnect) { - _onError(); + }, reconnectInterval); + } else { + _onError(500, "Unable to reconnect with fallback transport"); } } @@ -1357,6 +1374,9 @@ jQuery.atmosphere = function() { rq = request; } + rq.lastIndex = 0; + rq.readyState = 0; + // CORS fake using JSONP if ((rq.transport == 'jsonp') || ((rq.enableXDR) && (jQuery.atmosphere.checkCORSSupport()))) { _jsonp(rq); @@ -1380,6 +1400,14 @@ jQuery.atmosphere = function() { } } + var reconnectF = function() { + if (rq.reconnect && _requestCount++ < rq.maxReconnectOnClose) { + _reconnect(ajaxRequest, rq, true); + } else { + _onError(0, "maxReconnectOnClose reached"); + } + }; + if (rq.reconnect && ( rq.maxRequest == -1 || rq.requestCount++ < rq.maxRequest)) { var ajaxRequest = _buildAjaxRequest(); _doRequest(ajaxRequest, rq, true); @@ -1392,162 +1420,129 @@ jQuery.atmosphere = function() { _response.transport = rq.transport; } - if (!jQuery.browser.msie) { - ajaxRequest.onerror = function() { - try { - _response.status = XMLHttpRequest.status; - } catch(e) { - _response.status = 500; - } + ajaxRequest.onabort = function () { + _invokeClose(true); + }; - if (!_response.status) { - _response.status = 500; - } - _clearState(); + ajaxRequest.onerror = function() { + _response.error = true; + try { + _response.status = XMLHttpRequest.status; + } catch(e) { + _response.status = 500; + } - if (rq.reconnect) { - _reconnect(ajaxRequest, rq, true); - } else { - _onError(); - } - }; - } + if (!_response.status) { + _response.status = 500; + } + _clearState(); + if (!_response.errorHandled) { + reconnectF(); + } + }; ajaxRequest.onreadystatechange = function() { if (_abordingConnection) { return; } - + _response.error = null; var skipCallbackInvocation = false; var update = false; - // Remote server disconnected us, reconnect. - if (rq.transport == 'streaming' + + // Opera doesn't call onerror if the server disconnect. + if (jQuery.browser.opera + && rq.transport == 'streaming' && rq.readyState > 2 && ajaxRequest.readyState == 4) { rq.readyState = 0; rq.lastIndex = 0; - _reconnect(ajaxRequest, rq, true); + reconnectF(); return; } rq.readyState = ajaxRequest.readyState; - if (ajaxRequest.readyState == 4) { - if (jQuery.browser.msie) { - update = true; - } else if (rq.transport == 'streaming') { - update = true; - } else if (rq.transport == 'long-polling') { - update = true; - clearTimeout(rq.id); - } - } else if (rq.transport == 'streaming' && jQuery.browser.msie && ajaxRequest.readyState >= 3) { + if (rq.transport == 'streaming' && ajaxRequest.readyState >= 3) { update = true; - } else if (!jQuery.browser.msie && ajaxRequest.readyState == 3 && ajaxRequest.status == 200 && rq.transport != 'long-polling') { + } else if (rq.transport == 'long-polling' && ajaxRequest.readyState === 4) { update = true; - } else { - clearTimeout(rq.id); } + clearTimeout(rq.id); if (update) { + // MSIE 9 and lower status can be higher than 1000, Chrome can be 0 + var status = 0; + if (ajaxRequest.readyState != 0) { + status = ajaxRequest.status > 1000 ? 0 : ajaxRequest.status; + } + + if (status >= 300 || status == 0) { + // Prevent onerror callback to be called + _response.errorHandled = true; + _clearState(); + reconnectF(); + return; + } var responseText = ajaxRequest.responseText; - // MSIE status can be higher than 1000, Chrome can be 0 - if (ajaxRequest.status >= 500 || ajaxRequest.status == 0) { - if (rq.reconnect) { - _reconnect(ajaxRequest, rq, true); - } else { - _onError(); + if (jQuery.trim(responseText.length) == 0 && rq.transport == 'long-polling') { + // For browser that aren't support onabort + if (!ajaxRequest.hasData) { + reconnectF(); + } else { + ajaxRequest.hasData = false; } return; } + ajaxRequest.hasData = true; _readHeaders(ajaxRequest, _request); if (rq.transport == 'streaming') { - var text = responseText.substring(rq.lastIndex, responseText.length); - _response.isJunkEnded = true; - - //fix junk is comming in parts - if (!_response.junkFull && (text.indexOf("<!-- Welcome to the Atmosphere Framework.") == -1 || text.indexOf("<!-- EOD -->") == -1)) { - return; - } - _response.junkFull = true; - - //if it's the start and we see the junk start - //fix for reconnecting on chrome - junk is comming in parts - if (rq.lastIndex == 0 && text.indexOf("<!-- Welcome to the Atmosphere Framework.") != -1 && text.indexOf("<!-- EOD -->") != -1) { - _response.isJunkEnded = false; - } - - if (!_response.isJunkEnded) { - var endOfJunk = "<!-- EOD -->"; - var endOfJunkLength = endOfJunk.length; - var junkEnd = text.indexOf(endOfJunk) + endOfJunkLength; - - if (junkEnd > endOfJunkLength && junkEnd != text.length) { - _response.responseBody = text.substring(junkEnd); - rq.lastIndex = responseText.length; - if (!_handleProtocol( _request, _response.responseBody)) { - return; - } - skipCallbackInvocation = _trackMessageSize(_response.responseBody, rq, _response); - } else { - skipCallbackInvocation = true; - } - } else { + if (!jQuery.browser.opera) { var message = responseText.substring(rq.lastIndex, responseText.length); rq.lastIndex = responseText.length; - if (!_handleProtocol( _request, message)) { + if (!_handleProtocol(_request, message)) { return; } skipCallbackInvocation = _trackMessageSize(message, rq, _response); - } - rq.lastIndex = responseText.length; - - if (jQuery.browser.opera) { - jQuery.atmosphere.iterate(function() { - if (ajaxRequest.responseText.length > rq.lastIndex) { + } else { + jQuery.atmosphere.iterate(function () { + if (_response.status != 500 && ajaxRequest.responseText.length > rq.lastIndex) { try { _response.status = ajaxRequest.status; - _response.headers = parseHeaders(ajaxRequest.getAllResponseHeaders()); - - _readHeaders(ajaxRequest, _request); } - catch(e) { + catch (e) { _response.status = 404; } _response.state = "messageReceived"; - _response.responseBody = ajaxRequest.responseText.substring(rq.lastIndex); + + var message = ajaxRequest.responseText.substring(rq.lastIndex); rq.lastIndex = ajaxRequest.responseText.length; + if (_handleProtocol(_request, message)) { + skipCallbackInvocation = _trackMessageSize(message, rq, _response); + if (!skipCallbackInvocation) { + _invokeCallback(); + } - if (!_handleProtocol( _request, _response.responseBody)) { - _reconnect(ajaxRequest, rq, false); - return; - } - _invokeCallback(); - if ((rq.transport == 'streaming') && (ajaxRequest.responseText.length > rq.maxStreamingLength)) { - // Close and reopen connection on large data received - _clearState(); - _doRequest(_buildAjaxRequest(), rq, true); + _verifyStreamingLength(ajaxRequest, rq); } + } else if (_response.status > 400){ + rq.lastIndex = ajaxRequest.responseText.length; + return false; } }, 0); } - - if (skipCallbackInvocation) { - return; - } } else { if (!_handleProtocol( _request, responseText)) { _reconnect(ajaxRequest, rq, false); return; } - _trackMessageSize(responseText, rq, _response); + skipCallbackInvocation = _trackMessageSize(responseText, rq, _response); rq.lastIndex = responseText.length; } @@ -1575,17 +1570,15 @@ jQuery.atmosphere = function() { jQuery.atmosphere.log(rq.logLevel, ["parent.callback no longer supported with 0.8 version and up. Please upgrade"]); } - _invokeCallback(); + if (!skipCallbackInvocation) { + _invokeCallback(); + } if (rq.executeCallbackBeforeReconnect) { _reconnect(ajaxRequest, rq, false); } - if ((rq.transport == 'streaming') && (responseText.length > rq.maxStreamingLength)) { - // Close and reopen connection on large data received - _clearState(); - _doRequest(_buildAjaxRequest(), rq, true); - } + _verifyStreamingLength(ajaxRequest, rq); } }; ajaxRequest.send(rq.data); @@ -1606,7 +1599,7 @@ jQuery.atmosphere = function() { if (rq.logLevel == 'debug') { jQuery.atmosphere.log(rq.logLevel, ["Max re-connection reached."]); } - _onError(); + _onError(0, "maxRequest reached"); } } @@ -1651,13 +1644,13 @@ jQuery.atmosphere = function() { if (request.trackMessageLength) { ajaxRequest.setRequestHeader("X-Atmosphere-TrackMessageSize", "true") } - - if (request.contentType != '') { - ajaxRequest.setRequestHeader("Content-Type", request.contentType); - } ajaxRequest.setRequestHeader("X-Atmosphere-tracking-id", request.uuid); } + if (request.contentType != '') { + ajaxRequest.setRequestHeader("Content-Type", request.contentType); + } + jQuery.each(request.headers, function(name, value) { var h = jQuery.isFunction(value) ? value.call(this, ajaxRequest, request, create, _response) : value; if (h != null) { @@ -1667,17 +1660,26 @@ jQuery.atmosphere = function() { } function _reconnect(ajaxRequest, request, force) { - var reconnect = request.reconnect && _requestCount++ < request.maxReconnectOnClose; + if (force || request.transport != 'streaming') { + if ( request.reconnect || (request.suspend && _subscribed)) { + var status = 0; + if (ajaxRequest.readyState != 0) { + status = ajaxRequest.status > 1000 ? 0 : ajaxRequest.status; + } + _response.status = status == 0 ? 204 : status; + _response.reason = status == 0 ? "Server resumed the connection or down." : "OK"; - if (reconnect && force || (request.suspend && ajaxRequest.status == 200 && request.transport != 'streaming' && _subscribed)) { - if (request.reconnect) { - _open('re-opening', request.transport, request); - request.id = setTimeout(function() { - _executeRequest(); - }, request.reconnectInterval); + var reconnectInterval = (request.connectTimeout == -1) ? 0 : request.connectTimeout; + + // Reconnect immedialtely + if (!force) { + request.id = setTimeout(function () { + _executeRequest(request); + }, reconnectInterval); + } else { + _executeRequest(request); + } } - } else if (!reconnect) { - _onError(); } } @@ -1702,21 +1704,6 @@ jQuery.atmosphere = function() { var lastIndex = 0; var xdrCallback = function (xdr) { var responseBody = xdr.responseText; - var isJunkEnded = false; - - if (responseBody.indexOf("<!-- Welcome to the Atmosphere Framework.") != -1) { - isJunkEnded = true; - } - - if (isJunkEnded) { - var endOfJunk = "<!-- EOD -->"; - var endOfJunkLenght = endOfJunk.length; - var junkEnd = responseBody.indexOf(endOfJunk); - if (junkEnd !== -1) { - responseBody = responseBody.substring(junkEnd + endOfJunkLenght + lastIndex); - lastIndex += responseBody.length; - } - } if (!_handleProtocol(request, responseBody)) return; @@ -1747,10 +1734,8 @@ jQuery.atmosphere = function() { xdr.onerror = function() { // If the server doesn't send anything back to XDR will fail with polling if (rq.transport != 'polling') { - _prepareCallback(xdr.responseText, "error", 500, transport); + _reconnect(xdr, rq, false); } - - _reconnect(xdr, rq, false); }; // Handles close event @@ -1873,23 +1858,7 @@ jQuery.atmosphere = function() { clone.appendChild(cdoc.createTextNode(".")); var text = clone.innerText; - var isJunkEnded = true; - - if (text.indexOf("<!-- Welcome to the Atmosphere Framework.") == -1) { - isJunkEnded = false; - } - - if (isJunkEnded) { - var endOfJunk = "<!-- EOD -->"; - var endOfJunkLength = endOfJunk.length; - var junkEnd = text.indexOf(endOfJunk) + endOfJunkLength; - - text = text.substring(junkEnd); - } - text = text.substring(0, text.length - 1); - - _handleProtocol(rq, text); return text; }; @@ -1918,11 +1887,14 @@ jQuery.atmosphere = function() { var text = readResponse(); if (text.length > rq.lastIndex) { _response.status = 200; + _response.error = null; - // Empties response every time that it is handled - res.innerText = ""; - _prepareCallback(text, "messageReceived", 200, rq.transport); - + var message = text; + if (message.length != 0 && _handleProtocol(rq, message)) { + // Empties response every time that it is handled + res.innerText = ""; + _prepareCallback(message, "messageReceived", 200, rq.transport); + } rq.lastIndex = 0; } @@ -1938,12 +1910,13 @@ jQuery.atmosphere = function() { return false; } catch (err) { + _response.error = true; if (_requestCount++ < rq.maxReconnectOnClose) { rq.id = setTimeout(function() { _ieStreaming(rq); }, rq.reconnectInterval); } else { - _onError(); + _onError(0, "maxReconnectOnClose reached"); } doc.execCommand("Stop"); doc.close(); @@ -2095,6 +2068,7 @@ jQuery.atmosphere = function() { attachHeadersAsQueryString: true, enableXDR: _request.enableXDR, uuid : _request.uuid, + messageDelimiter : '|', enableProtocol : false, maxReconnectOnClose : _request.maxReconnectOnClose }; @@ -2147,11 +2121,11 @@ jQuery.atmosphere = function() { } function _prepareCallback(messageBody, state, errorCode, transport) { - _response.responseBody = messageBody; + if (state == "messageReceived") { - if (_trackMessageSize(messageBody, _request, _response)) { - return; - } + if (_trackMessageSize(messageBody, _request, _response)) return; + } else { + _response.responseBody = messageBody; } _response.transport = transport; @@ -2225,6 +2199,14 @@ jQuery.atmosphere = function() { } } + function _invokeClose(wasOpen) { + _response.state = 'closed'; + _response.responseBody = ""; + _response.messages = []; + _response.status = !wasOpen ? 501 : 200; + _invokeCallback(); + } + /** * Invoke request callbacks. * @@ -2242,7 +2224,7 @@ jQuery.atmosphere = function() { _request.reconnect = _request.mrequest; var messages = (typeof(_response.responseBody) == 'string' && _request.trackMessageLength) ? - _response.responseBody.split(_request.messageDelimiter) : new Array(_response.responseBody); + (_response.messages.length>0 ? _response.messages : ['']) : new Array(_response.responseBody); for (var i = 0; i < messages.length; i++) { if (messages.length > 1 && messages[i].length == 0) { @@ -2250,13 +2232,8 @@ jQuery.atmosphere = function() { } _response.responseBody = jQuery.trim(messages[i]); - // Ugly see issue 400. - if (_response.responseBody.length == 0 && _response.transport == 'streaming' && _response.state == "messageReceived") { - var ua = navigator.userAgent.toLowerCase(); - var isAndroid = ua.indexOf("android") > -1; - if (isAndroid) { - continue; - } + if (_response.responseBody.length == 0 && _response.state == "messageReceived") { + continue; } _invokeFunction(_response); @@ -2289,16 +2266,52 @@ jQuery.atmosphere = function() { } /** + * + * @private + */ + function _verifyStreamingLength(ajaxRequest, rq){ + // Wait to be sure we have the full message before closing. + if (_response.partialMessage == "" && + (rq.transport == 'streaming') && + (ajaxRequest.responseText.length > rq.maxStreamingLength)) { + _response.messages = []; + _invokeClose(true); + _disconnect(); + _clearState(); + _reconnect(ajaxRequest, rq, true); + } + } + + /** + * Disconnect + * @private + */ + function _disconnect() { + if (_request.enableProtocol) { + var query = "X-Atmosphere-Transport=close&X-Atmosphere-tracking-id=" + _request.uuid; + var url = _request.url.replace(/([?&])_=[^&]*/, query); + url = url + (url === _request.url ? (/\?/.test(_request.url) ? "&" : "?") + query : ""); + + if (_request.connectTimeout > -1) { + jQuery.ajax({url: url, async: false, timeout: _request.connectTimeout}); + } else { + jQuery.ajax({url: url, async: false}); + } + } + } + + /** * Close request. * * @private */ function _close() { - _abordingConnection = true; _request.reconnect = false; + _abordingConnection = true; _response.request = _request; _response.state = 'unsubscribe'; _response.responseBody = ""; + _response.messages = []; _response.status = 408; _invokeCallback(); @@ -2319,7 +2332,9 @@ jQuery.atmosphere = function() { _activeRequest = null; } if (_websocket != null) { - _websocket.close(); + if (_websocket.webSocketOpened) { + _websocket.close(); + } _websocket = null; } if (_sse != null) { @@ -2343,7 +2358,7 @@ jQuery.atmosphere = function() { if (_localStorageService != null) { _localStorageService.close(); } - } + }; this.subscribe = function(options) { _subscribe(options); @@ -2362,6 +2377,10 @@ jQuery.atmosphere = function() { _close(); }; + this.disconnect = function () { + _disconnect(); + }; + this.getUrl = function() { return _request.url; }; @@ -2421,10 +2440,8 @@ jQuery.atmosphere = function() { var requestsClone = [].concat(jQuery.atmosphere.requests); for (var i = 0; i < requestsClone.length; i++) { var rq = requestsClone[i]; + rq.disconnect(); rq.close(); - if (rq.enableProtocol()) { - jQuery.ajax({url: this._closeUrl(rq), async:false}); - } clearTimeout(rq.response.request.id); } } @@ -2432,12 +2449,6 @@ jQuery.atmosphere = function() { jQuery.atmosphere.callbacks = []; }, - _closeUrl : function(rq) { - var query = "X-Atmosphere-Transport=close&X-Atmosphere-tracking-id=" + rq.getUUID(); - var url = rq.getUrl().replace(/([?&])_=[^&]*/, query); - return url + (url === rq.getUrl() ? (/\?/.test(rq.getUrl()) ? "&" : "?") + query : ""); - }, - unsubscribeUrl: function(url) { var idx = -1; if (jQuery.atmosphere.requests.length > 0) { @@ -2446,10 +2457,8 @@ jQuery.atmosphere = function() { // Suppose you can subscribe once to an url if (rq.getUrl() == url) { + rq.disconnect(); rq.close(); - if (rq.enableProtocol()) { - jQuery.ajax({url :this._closeUrl(rq), async:false}); - } clearTimeout(rq.response.request.id); idx = i; break; @@ -2643,8 +2652,8 @@ jQuery.atmosphere = function() { /* * jQuery stringifyJSON * http://github.com/flowersinthesand/jquery-stringifyJSON - * - * Copyright 2011, Donghwan Kim + * + * Copyright 2011, Donghwan Kim * Licensed under the Apache License, Version 2.0 * http://www.apache.org/licenses/LICENSE-2.0 */ @@ -2728,4 +2737,4 @@ jQuery.atmosphere = function() { return str("", {"": value}); }; -}(jQuery));
\ No newline at end of file +}(jQuery)); diff --git a/WebContent/VAADIN/themes/base/base.scss b/WebContent/VAADIN/themes/base/base.scss index 83e463fa00..514579830d 100644 --- a/WebContent/VAADIN/themes/base/base.scss +++ b/WebContent/VAADIN/themes/base/base.scss @@ -88,7 +88,10 @@ $line-height: normal; @include base-orderedlayout; @include base-panel; @include base-popupview; - @include base-progressindicator; + @include base-progressindicator(v-progressbar); + /* For legacy ProgressIndicator component */ + @include base-progressindicator(v-progressindicator); + @include base-select; @include base-shadow; @include base-slider; diff --git a/WebContent/VAADIN/themes/base/debug/debug.scss b/WebContent/VAADIN/themes/base/debug/debug.scss index 687370270e..209c3e0469 100644 --- a/WebContent/VAADIN/themes/base/debug/debug.scss +++ b/WebContent/VAADIN/themes/base/debug/debug.scss @@ -207,13 +207,22 @@ .v-debugwindow-row:nth-child(odd) { background-color: rgba(0, 61, 255, 0.11); } - .v-debugwindow-row.ERROR { + .v-debugwindow-row.SEVERE { color: #550000; background-color: #FFC5C5; } .v-debugwindow-row.WARNING { background-color: #FFFF99; } + .v-debugwindow-row.FINE { + color: lighten($maincolor, 5%); + } + .v-debugwindow-row.FINER { + color: lighten($maincolor, 10%); + } + .v-debugwindow-row.FINEST { + color: lighten($maincolor, 15%); + } .v-debugwindow-row > span { display: table-cell; diff --git a/WebContent/VAADIN/themes/chameleon/components/components.scss b/WebContent/VAADIN/themes/chameleon/components/components.scss index 9f29827de0..9c8a56b33d 100644 --- a/WebContent/VAADIN/themes/chameleon/components/components.scss +++ b/WebContent/VAADIN/themes/chameleon/components/components.scss @@ -29,7 +29,11 @@ @include chameleon-notification; @include chameleon-panel; @include chameleon-popupview; - @include chameleon-progressindicator; + + @include chameleon-progressindicator(v-progressbar); + /* For legacy ProgressIndicator component */ + @include chameleon-progressindicator(v-progressindicator); + @include chameleon-slider; @include chameleon-splitpanel; @include chameleon-table; diff --git a/WebContent/VAADIN/themes/liferay/liferay.scss b/WebContent/VAADIN/themes/liferay/liferay.scss index 7d7665ad86..273c065772 100644 --- a/WebContent/VAADIN/themes/liferay/liferay.scss +++ b/WebContent/VAADIN/themes/liferay/liferay.scss @@ -42,7 +42,9 @@ @include liferay-notification; @include liferay-panel; @include liferay-popupview; - @include liferay-progressindicator; + @include liferay-progressindicator(v-progressbar); + /* For legacy ProgressIndicator component */ + @include liferay-progressindicator(v-progressindicator); @include liferay-select; @include liferay-slider; @include liferay-splitpanel; diff --git a/WebContent/VAADIN/themes/reindeer/reindeer.scss b/WebContent/VAADIN/themes/reindeer/reindeer.scss index 3cf1c392e3..485839ecc7 100644 --- a/WebContent/VAADIN/themes/reindeer/reindeer.scss +++ b/WebContent/VAADIN/themes/reindeer/reindeer.scss @@ -56,7 +56,10 @@ $line-height: normal; @include reindeer-notification; @include reindeer-panel; @include reindeer-popupview; - @include reindeer-progressindicator; + @include reindeer-progressindicator(v-progressbar); + /* For legacy ProgressIndicator component */ + @include reindeer-progressindicator(v-progressindicator); + @include reindeer-select; @include reindeer-slider; @include reindeer-splitpanel; diff --git a/WebContent/VAADIN/themes/runo/runo.scss b/WebContent/VAADIN/themes/runo/runo.scss index 6e88b14eb4..33ad35a8af 100644 --- a/WebContent/VAADIN/themes/runo/runo.scss +++ b/WebContent/VAADIN/themes/runo/runo.scss @@ -58,7 +58,11 @@ $line-height: 18px; @include runo-orderedlayout; @include runo-panel; @include runo-popupview; - @include runo-progressindicator; + + @include runo-progressindicator(v-progressbar); + /* For legacy ProgressIndicator component */ + @include runo-progressindicator(v-progressindicator); + @include runo-select; @include runo-shadow; @include runo-slider; diff --git a/WebContent/VAADIN/themes/runo/window/img/dialog/maximize.png b/WebContent/VAADIN/themes/runo/window/img/dialog/maximize.png Binary files differnew file mode 100644 index 0000000000..cbbc0f6691 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/window/img/dialog/maximize.png diff --git a/WebContent/VAADIN/themes/runo/window/img/dialog/restore.png b/WebContent/VAADIN/themes/runo/window/img/dialog/restore.png Binary files differnew file mode 100644 index 0000000000..a4e9d257e1 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/window/img/dialog/restore.png diff --git a/WebContent/VAADIN/themes/runo/window/window.scss b/WebContent/VAADIN/themes/runo/window/window.scss index d2048e027e..1a7cfd3b01 100644 --- a/WebContent/VAADIN/themes/runo/window/window.scss +++ b/WebContent/VAADIN/themes/runo/window/window.scss @@ -57,7 +57,6 @@ position: absolute; top: 21px; height: 12px; - background: transparent url(img/close.png); } .#{$primaryStyleName}-closebox { width: 12px; @@ -99,30 +98,56 @@ /* Dialog style */ .#{$primaryStyleName}-dialog { background-image: url(img/dialog/bottom-left.png); + + .#{$primaryStyleName}-outerheader { + height: 32px; + padding: 13px 30px 5px 8px; + background: transparent url(img/top-right.png) no-repeat right top; + } + .#{$primaryStyleName}-header { + font-size: 12px; + line-height: normal; + font-weight: bold; + letter-spacing: 0; + text-shadow: 0 1px 0 #fff; + } + .#{$primaryStyleName}-contents > div { + background: #f1f3f3; + } + div.#{$primaryStyleName}-footer { + background-image: url(img/dialog/bottom-right.png); + } + .#{$primaryStyleName}-closebox { + top: 14px; + right: 16px; + background-image: url(img/dialog/close.png); + } + + .#{$primaryStyleName}-restorebox { + width: 12px; + height: 12px; + top: 15px; + right: 32px; + + background: transparent url(img/dialog/restore.png); + &:hover { + background-position: 0 -12px; + } + } + + .#{$primaryStyleName}-maximizebox { + width: 11px; + height: 10px; + top: 15px; + right: 32px; + + background: transparent url(img/dialog/maximize.png); + &:hover { + background-position: 0 -10px; + } + } } -.#{$primaryStyleName}-dialog .#{$primaryStyleName}-outerheader { - height: 32px; - padding: 13px 30px 5px 8px; - background: transparent url(img/top-right.png) no-repeat right top; -} -.#{$primaryStyleName}-dialog .#{$primaryStyleName}-header { - font-size: 12px; - line-height: normal; - font-weight: bold; - letter-spacing: 0; - text-shadow: 0 1px 0 #fff; -} -.#{$primaryStyleName}-dialog .#{$primaryStyleName}-contents > div { - background: #f1f3f3; -} -.#{$primaryStyleName}-dialog div.#{$primaryStyleName}-footer { - background-image: url(img/dialog/bottom-right.png); -} -.#{$primaryStyleName}-dialog .#{$primaryStyleName}-closebox { - top: 14px; - right: 16px; - background-image: url(img/dialog/close.png); -} + /* Shadow for window */ .v-shadow-window .top-left { top: -13px; left: -20px; diff --git a/WebContent/VAADIN/vaadinPush.js.tpl b/WebContent/VAADIN/vaadinPush.js.tpl index 3928fba1b6..43dfd18b40 100644 --- a/WebContent/VAADIN/vaadinPush.js.tpl +++ b/WebContent/VAADIN/vaadinPush.js.tpl @@ -3,6 +3,6 @@ window.jQueryVaadin = window.jQuery.noConflict(true); (function(jQuery, undefined) { @jquery.atmosphere.js@ })(jQueryVaadin); -if (console) { - console.log("Vaadin push loaded"); -}
\ No newline at end of file +if (window.console) { + window.console.log("Vaadin push loaded"); +} diff --git a/WebContent/WEB-INF/liferay-display.xml b/WebContent/WEB-INF/liferay-display.xml index 12a8e4315b..014ed31b47 100644 --- a/WebContent/WEB-INF/liferay-display.xml +++ b/WebContent/WEB-INF/liferay-display.xml @@ -4,6 +4,6 @@ <display> <category name="Vaadin"> <portlet id="JSR286TestPortlet" /> - <portlet id="Vaadin Liferay Theme Portlet"/> + <portlet id="Vaadin Liferay Theme Portlet" /> </category> </display>
\ No newline at end of file diff --git a/WebContent/WEB-INF/liferay-portlet.xml b/WebContent/WEB-INF/liferay-portlet.xml index 5a8d6fac8e..ea060ce44a 100644 --- a/WebContent/WEB-INF/liferay-portlet.xml +++ b/WebContent/WEB-INF/liferay-portlet.xml @@ -4,7 +4,7 @@ <liferay-portlet-app> <portlet> <portlet-name>JSR286TestPortlet</portlet-name> - <instanceable>false</instanceable> + <instanceable>false</instanceable> <ajaxable>false</ajaxable> </portlet> <portlet> @@ -12,7 +12,7 @@ <instanceable>false</instanceable> <ajaxable>false</ajaxable> </portlet> - + <role-mapper> <role-name>administrator</role-name> <role-link>Administrator</role-link> @@ -29,5 +29,5 @@ <role-name>user</role-name> <role-link>User</role-link> </role-mapper> - + </liferay-portlet-app>
\ No newline at end of file diff --git a/WebContent/WEB-INF/portlet.xml b/WebContent/WEB-INF/portlet.xml index 45ce1eee83..3a603c43ae 100644 --- a/WebContent/WEB-INF/portlet.xml +++ b/WebContent/WEB-INF/portlet.xml @@ -1,85 +1,79 @@ <?xml version="1.0" encoding="UTF-8"?> <portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" - version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"> + version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"> - <portlet> - <portlet-name>JSR286TestPortlet</portlet-name> - <display-name>Vaadin Portlet 2.0 Test</display-name> - <portlet-class>com.vaadin.server.VaadinPortlet</portlet-class> - <init-param> - <name>ui</name> - <value>com.vaadin.tests.integration.JSR286Portlet</value> - </init-param> - <init-param> - <name>widgetset</name> - <value>com.vaadin.DefaultWidgetSet</value> - </init-param> - <supports> - <mime-type>text/html</mime-type> - <portlet-mode>view</portlet-mode> - <portlet-mode>edit</portlet-mode> - <portlet-mode>help</portlet-mode> - </supports> - <portlet-info> - <title>Vaadin Portlet 2.0 Test</title> - <short-title>Vaadin Portlet 2.0 Test</short-title> - </portlet-info> + <portlet> + <portlet-name>JSR286TestPortlet</portlet-name> + <display-name>Vaadin Portlet 2.0 Test</display-name> + <portlet-class>com.vaadin.server.VaadinPortlet</portlet-class> + <init-param> + <name>ui</name> + <value>com.vaadin.tests.integration.JSR286Portlet</value> + </init-param> + <init-param> + <name>widgetset</name> + <value>com.vaadin.DefaultWidgetSet</value> + </init-param> + <supports> + <mime-type>text/html</mime-type> + <portlet-mode>view</portlet-mode> + <portlet-mode>edit</portlet-mode> + <portlet-mode>help</portlet-mode> + </supports> + <portlet-info> + <title>Vaadin Portlet 2.0 Test</title> + <short-title>Vaadin Portlet 2.0 Test</short-title> + </portlet-info> - <security-role-ref> - <role-name>administrator</role-name> - </security-role-ref> - <security-role-ref> - <role-name>guest</role-name> - </security-role-ref> - <security-role-ref> - <role-name>power-user</role-name> - </security-role-ref> - <security-role-ref> - <role-name>user</role-name> - </security-role-ref> - </portlet> + <security-role-ref> + <role-name>administrator</role-name> + </security-role-ref> + <security-role-ref> + <role-name>guest</role-name> + </security-role-ref> + <security-role-ref> + <role-name>power-user</role-name> + </security-role-ref> + <security-role-ref> + <role-name>user</role-name> + </security-role-ref> + </portlet> - <portlet> + <portlet> <portlet-name>Vaadin Liferay Theme Portlet</portlet-name> <display-name>Vaadin Liferay Theme</display-name> - + <portlet-class>com.vaadin.server.LegacyVaadinPortlet</portlet-class> <init-param> <name>application</name> <value>com.vaadin.tests.integration.LiferayThemeDemo</value> </init-param> - + <supports> <mime-type>text/html</mime-type> <portlet-mode>view</portlet-mode> </supports> - + <portlet-info> <title>Vaadin Liferay Theme</title> <short-title>Vaadin Liferay Theme</short-title> </portlet-info> - + + <security-role-ref> + <role-name>administrator</role-name> + </security-role-ref> + <security-role-ref> + <role-name>guest</role-name> + </security-role-ref> <security-role-ref> - <role-name>administrator</role-name> - </security-role-ref> - <security-role-ref> - <role-name>guest</role-name> - </security-role-ref> - <security-role-ref> - <role-name>power-user</role-name> - </security-role-ref> - <security-role-ref> - <role-name>user</role-name> - </security-role-ref> + <role-name>power-user</role-name> + </security-role-ref> + <security-role-ref> + <role-name>user</role-name> + </security-role-ref> </portlet> - <!-- - This can be used to work around an issue in liferay 5.0-5.1.1 - - <container-runtime-option> - <name>javax.portlet.escapeXml</name> - <value>false</value> - </container-runtime-option> - --> + <!-- This can be used to work around an issue in liferay 5.0-5.1.1 <container-runtime-option> + <name>javax.portlet.escapeXml</name> <value>false</value> </container-runtime-option> --> </portlet-app>
\ No newline at end of file diff --git a/WebContent/WEB-INF/web.xml b/WebContent/WEB-INF/web.xml index 848baea318..ba948968e2 100644 --- a/WebContent/WEB-INF/web.xml +++ b/WebContent/WEB-INF/web.xml @@ -1,134 +1,134 @@ <?xml version="1.0" encoding="UTF-8"?> <web-app id="vaadin-uitest" version="3.0" - xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> + xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> - <!-- THIS IS A DEVELOPMENT AND TESTING web.xml . --> + <!-- THIS IS A DEVELOPMENT AND TESTING web.xml . --> - <display-name>Vaadin</display-name> - <description>Vaadin examples</description> + <display-name>Vaadin</display-name> + <description>Vaadin examples</description> - <context-param> - <param-name>productionMode</param-name> - <param-value>false</param-value> - </context-param> + <context-param> + <param-name>productionMode</param-name> + <param-value>false</param-value> + </context-param> - <context-param> - <param-name>resourceCacheTime</param-name> - <param-value>3600</param-value> - </context-param> - <servlet> - <servlet-name>Embed App 1</servlet-name> - <servlet-class>com.vaadin.server.LegacyVaadinServlet</servlet-class> - <init-param> - <param-name>application</param-name> - <param-value>com.vaadin.tests.components.button.Buttons</param-value> - </init-param> - </servlet> - <servlet> - <servlet-name>Embed App 2</servlet-name> - <servlet-class>com.vaadin.server.VaadinServlet</servlet-class> - <init-param> - <param-name>UI</param-name> - <param-value>com.vaadin.tests.components.label.MarginsInLabels</param-value> - </init-param> - </servlet> - <servlet> - <servlet-name>UI provider app</servlet-name> - <servlet-class>com.vaadin.server.VaadinServlet</servlet-class> - <init-param> - <param-name>UIProvider</param-name> - <param-value>com.vaadin.tests.applicationservlet.InitParamUIProvider</param-value> - </init-param> - <init-param> - <param-name>UI</param-name> - <param-value>com.vaadin.tests.VerifyAssertionsEnabled</param-value> - </init-param> - </servlet> + <context-param> + <param-name>resourceCacheTime</param-name> + <param-value>3600</param-value> + </context-param> + <servlet> + <servlet-name>Embed App 1</servlet-name> + <servlet-class>com.vaadin.server.LegacyVaadinServlet</servlet-class> + <init-param> + <param-name>application</param-name> + <param-value>com.vaadin.tests.components.button.Buttons</param-value> + </init-param> + </servlet> + <servlet> + <servlet-name>Embed App 2</servlet-name> + <servlet-class>com.vaadin.server.VaadinServlet</servlet-class> + <init-param> + <param-name>UI</param-name> + <param-value>com.vaadin.tests.components.label.MarginsInLabels</param-value> + </init-param> + </servlet> + <servlet> + <servlet-name>UI provider app</servlet-name> + <servlet-class>com.vaadin.server.VaadinServlet</servlet-class> + <init-param> + <param-name>UIProvider</param-name> + <param-value>com.vaadin.tests.applicationservlet.InitParamUIProvider</param-value> + </init-param> + <init-param> + <param-name>UI</param-name> + <param-value>com.vaadin.tests.VerifyAssertionsEnabled</param-value> + </init-param> + </servlet> - <servlet> - <servlet-name>VaadinApplicationRunner</servlet-name> - <servlet-class>com.vaadin.launcher.ApplicationRunnerServlet</servlet-class> - <!-- Non-default values for testing purposes --> - <init-param> - <param-name>legacyPropertyToString</param-name> - <param-value>false</param-value> - </init-param> - <init-param> - <param-name>heartbeatInterval</param-name> - <param-value>301</param-value> - </init-param> - <init-param> - <param-name>resourceCacheTime</param-name> - <param-value>3601</param-value> - </init-param> - <init-param> - <param-name>closeIdleSessions</param-name> - <param-value>true</param-value> - </init-param> - <init-param> - <param-name>testParam</param-name> - <param-value>42</param-value> - </init-param> - </servlet> + <servlet> + <servlet-name>VaadinApplicationRunner</servlet-name> + <servlet-class>com.vaadin.launcher.ApplicationRunnerServlet</servlet-class> + <!-- Non-default values for testing purposes --> + <init-param> + <param-name>legacyPropertyToString</param-name> + <param-value>false</param-value> + </init-param> + <init-param> + <param-name>heartbeatInterval</param-name> + <param-value>301</param-value> + </init-param> + <init-param> + <param-name>resourceCacheTime</param-name> + <param-value>3601</param-value> + </init-param> + <init-param> + <param-name>closeIdleSessions</param-name> + <param-value>true</param-value> + </init-param> + <init-param> + <param-name>testParam</param-name> + <param-value>42</param-value> + </init-param> + </servlet> - <servlet> - <servlet-name>VaadinApplicationRunnerWithPush</servlet-name> - <servlet-class>com.vaadin.launcher.ApplicationRunnerServlet</servlet-class> - <init-param> - <param-name>pushmode</param-name> - <param-value>automatic</param-value> - </init-param> - <async-supported>true</async-supported> - </servlet> + <servlet> + <servlet-name>VaadinApplicationRunnerWithPush</servlet-name> + <servlet-class>com.vaadin.launcher.ApplicationRunnerServlet</servlet-class> + <init-param> + <param-name>pushmode</param-name> + <param-value>automatic</param-value> + </init-param> + <async-supported>true</async-supported> + </servlet> - <!-- For testing GAE - the deployment script changes this to use GAEVaadinServlet --> - <servlet> - <servlet-name>IntegrationTest</servlet-name> - <servlet-class>com.vaadin.server.VaadinServlet</servlet-class> - <init-param> - <param-name>UI</param-name> - <param-value>com.vaadin.tests.integration.IntegrationTestUI</param-value> - </init-param> - <async-supported>true</async-supported> - </servlet> - <servlet-mapping> - <servlet-name>Embed App 1</servlet-name> - <url-pattern>/embed1/*</url-pattern> - </servlet-mapping> + <!-- For testing GAE - the deployment script changes this to use GAEVaadinServlet --> + <servlet> + <servlet-name>IntegrationTest</servlet-name> + <servlet-class>com.vaadin.server.VaadinServlet</servlet-class> + <init-param> + <param-name>UI</param-name> + <param-value>com.vaadin.tests.integration.IntegrationTestUI</param-value> + </init-param> + <async-supported>true</async-supported> + </servlet> + <servlet-mapping> + <servlet-name>Embed App 1</servlet-name> + <url-pattern>/embed1/*</url-pattern> + </servlet-mapping> - <servlet-mapping> - <servlet-name>Embed App 2</servlet-name> - <url-pattern>/embed2/*</url-pattern> - </servlet-mapping> + <servlet-mapping> + <servlet-name>Embed App 2</servlet-name> + <url-pattern>/embed2/*</url-pattern> + </servlet-mapping> - <servlet-mapping> - <servlet-name>UI provider app</servlet-name> - <url-pattern>/uiprovider/*</url-pattern> - </servlet-mapping> + <servlet-mapping> + <servlet-name>UI provider app</servlet-name> + <url-pattern>/uiprovider/*</url-pattern> + </servlet-mapping> - <servlet-mapping> - <servlet-name>VaadinApplicationRunner</servlet-name> - <url-pattern>/run/*</url-pattern> - </servlet-mapping> + <servlet-mapping> + <servlet-name>VaadinApplicationRunner</servlet-name> + <url-pattern>/run/*</url-pattern> + </servlet-mapping> - <servlet-mapping> - <servlet-name>VaadinApplicationRunnerWithPush</servlet-name> - <url-pattern>/run-push/*</url-pattern> - </servlet-mapping> + <servlet-mapping> + <servlet-name>VaadinApplicationRunnerWithPush</servlet-name> + <url-pattern>/run-push/*</url-pattern> + </servlet-mapping> - <servlet-mapping> - <servlet-name>IntegrationTest</servlet-name> - <url-pattern>/integration/*</url-pattern> - </servlet-mapping> + <servlet-mapping> + <servlet-name>IntegrationTest</servlet-name> + <url-pattern>/integration/*</url-pattern> + </servlet-mapping> - <servlet-mapping> - <servlet-name>IntegrationTest</servlet-name> - <url-pattern>/VAADIN/*</url-pattern> - </servlet-mapping> + <servlet-mapping> + <servlet-name>IntegrationTest</servlet-name> + <url-pattern>/VAADIN/*</url-pattern> + </servlet-mapping> - <welcome-file-list> - <welcome-file>index.html</welcome-file> - </welcome-file-list> + <welcome-file-list> + <welcome-file>index.html</welcome-file> + </welcome-file-list> </web-app> diff --git a/all/build.xml b/all/build.xml index 4e1a557e53..a83d60b382 100644 --- a/all/build.xml +++ b/all/build.xml @@ -1,120 +1,137 @@ <?xml version="1.0"?> -<project name="vaadin-all" basedir="." default="publish-local" xmlns:ivy="antlib:org.apache.ivy.ant" xmlns:antcontrib="antlib:net.sf.antcontrib"> - <description> - Compiles a zip containing all jars + dependencies - </description> - <include file="../common.xml" as="common" /> - <include file="../build.xml" as="vaadin" /> - - <!-- global properties --> - <property name="module.name" value="vaadin-all" /> - <property name="result.dir" value="result" /> - <property name="javadoc.jar" location="${result.dir}/lib/vaadin-all-${vaadin.version}-javadoc.jar" /> - <property name="temp.dir" location="${result.dir}/temp" /> - <property name="temp.deps.dir" value="${temp.dir}/lib" /> - <property name="javadoc.temp.dir" location="${result.dir}/javadoc-temp" /> - <property name="zip.file" location="${result.dir}/lib/${module.name}-${vaadin.version}.zip" /> - - <path id="classpath.javadoc"> - <fileset dir="${temp.deps.dir}" includes="*.jar"> - </fileset> - </path> - <target name="fetch.module.and.dependencies"> - <fail unless="module" message="No 'module' parameter given" /> - - <ivy:cachepath pathid="module.and.deps" inline="true" organisation="com.vaadin" module="vaadin-${module}" revision="${vaadin.version}" /> - <copy todir="${temp.dir}" flatten="true"> - <path refid="module.and.deps" /> - </copy> - </target> - - <target name="unzip.to.javadoctemp"> - <property name="file" location="${temp.dir}/vaadin-${module}-${vaadin.version}.jar" /> - <unzip src="${file}" dest="${javadoc.temp.dir}" /> - </target> - - <target name="javadoc" depends="copy-jars"> - <!-- Ensure filtered webcontent files are available --> - <antcall target="common.filter.webcontent" /> - - <!-- Unpack all source files to javadoc.temp.dir--> - <antcontrib:foreach list="${modules.to.publish.to.maven}" target="unzip.to.javadoctemp" param="module" /> - - <property name="javadoc.dir" location="${result.dir}/javadoc" /> - <property name="title" value="Vaadin ${vaadin.version} API" /> - <javadoc maxmemory="1024m" destdir="${javadoc.dir}" author="true" version="true" use="true" windowtitle="${title}" encoding="utf-8"> - <packageset dir="${javadoc.temp.dir}"> - <!-- TODO Javadoc throws ClassCastException if this is included (#9660)--> - <exclude name="com/google/gwt/uibinder/elementparsers" /> - </packageset> - <doctitle><h1>${title}</h1></doctitle> - <!-- <header><![CDATA[<script type="text/javascript" src=".html-style/style.js"></script>]]></header> --> - <bottom>${javadoc.bottom}</bottom> - <link offline="true" href="http://docs.oracle.com/javase/6/docs/api/" packagelistLoc="build/javadoc/j2se-1.6.0" /> - <link offline="true" href="http://java.sun.com/j2ee/1.4/docs/api/" packagelistLoc="build/javadoc/j2ee-1.4" /> - <classpath refid="classpath.javadoc" /> - </javadoc> - - <!-- Create a javadoc jar --> - <jar file="${javadoc.jar}" compress="true"> - <fileset dir="${javadoc.dir}" /> - <fileset refid="common.files.for.all.jars" /> - </jar> - - - </target> - - <target name="copy-jars"> - <delete dir="${temp.dir}" /> - <antcontrib:foreach list="${modules.to.publish.to.maven}" target="fetch.module.and.dependencies" param="module" /> - <!-- All jars are now in temp.dir. Still need to separate vaadin and deps --> - <move todir="${temp.deps.dir}"> - <fileset dir="${temp.dir}"> - <exclude name="vaadin-*-${vaadin.version}.*" /> - <exclude name="vaadin-*-${vaadin.version}-*.*" /> - </fileset> - </move> - - - </target> - <target name="zip" depends="copy-jars, javadoc"> - <!-- Ensure filtered webcontent files are available --> - <antcall target="common.filter.webcontent" /> - - <zip destfile="${zip.file}"> - <fileset dir="${temp.dir}"> - <!-- Avoid conflicts with servlet and portlet API. They are provided by the container --> - <exclude name="**/servlet-api*" /> - <exclude name="**/portlet-api*" /> - <!-- Buildhelpers should not even get here ... --> - <exclude name="*buildhelpers*" /> - <!-- Zip users should not need javadoc, sources or pom files --> - <exclude name="*.pom" /> - <exclude name="*-javadoc.jar" /> - <exclude name="*-sources.jar" /> - - </fileset> - <fileset refid="common.files.for.all.jars" /> - <fileset dir="${result.dir}/.."> - <include name="README.TXT" /> - </fileset> - <!-- Do not include javadoc jar in zip as it is huge (> 40MB) and most people do not need it. --> - </zip> - </target> - - <target name="publish-local" depends="zip"> - <antcall target="common.publish-local" /> - </target> - - <target name="clean"> - <antcall target="common.clean" /> - </target> - <target name="checkstyle"> - <!-- Checkstyle is handled by all separate modules --> - </target> - <target name="test" depends="checkstyle"> - <!-- No tests for this zip.. --> - </target> +<project name="vaadin-all" basedir="." default="publish-local" + xmlns:ivy="antlib:org.apache.ivy.ant" xmlns:antcontrib="antlib:net.sf.antcontrib"> + <description> + Compiles a zip containing all jars + dependencies + </description> + <include file="../common.xml" as="common" /> + <include file="../build.xml" as="vaadin" /> + + <!-- global properties --> + <property name="module.name" value="vaadin-all" /> + <property name="result.dir" value="result" /> + <property name="javadoc.jar" + location="${result.dir}/lib/vaadin-all-${vaadin.version}-javadoc.jar" /> + <property name="temp.dir" location="${result.dir}/temp" /> + <property name="temp.deps.dir" value="${temp.dir}/lib" /> + <property name="javadoc.temp.dir" location="${result.dir}/javadoc-temp" /> + <property name="zip.file" + location="${result.dir}/lib/${module.name}-${vaadin.version}.zip" /> + + <path id="classpath.javadoc"> + <fileset dir="${temp.deps.dir}" includes="*.jar"> + </fileset> + </path> + <target name="fetch.module.and.dependencies"> + <fail unless="module" message="No 'module' parameter given" /> + + <ivy:cachepath pathid="module.and.deps" inline="true" + organisation="com.vaadin" module="vaadin-${module}" + revision="${vaadin.version}" /> + <copy todir="${temp.dir}" flatten="true"> + <path refid="module.and.deps" /> + </copy> + </target> + + <target name="unzip.to.javadoctemp"> + <property name="file" + location="${temp.dir}/vaadin-${module}-${vaadin.version}.jar" /> + <unzip src="${file}" dest="${javadoc.temp.dir}" /> + </target> + + <target name="javadoc" depends="copy-jars"> + <!-- Ensure filtered webcontent files are available --> + <antcall target="common.filter.webcontent" /> + + <!-- Unpack all source files to javadoc.temp.dir --> + <antcontrib:foreach list="${modules.to.publish.to.maven}" + target="unzip.to.javadoctemp" param="module" /> + + <property name="javadoc.dir" location="${result.dir}/javadoc" /> + <property name="title" value="Vaadin ${vaadin.version} API" /> + <javadoc maxmemory="1024m" destdir="${javadoc.dir}" + author="true" version="true" use="true" windowtitle="${title}" + encoding="utf-8"> + <packageset dir="${javadoc.temp.dir}"> + <!-- TODO Javadoc throws ClassCastException if this is included + (#9660) --> + <exclude name="com/google/gwt/uibinder/elementparsers" /> + </packageset> + <doctitle><h1>${title}</h1></doctitle> + <!-- <header><![CDATA[<script type="text/javascript" src=".html-style/style.js"></script>]]></header> --> + <bottom>${javadoc.bottom}</bottom> + <link offline="true" + href="http://docs.oracle.com/javase/6/docs/api/" + packagelistLoc="build/javadoc/j2se-1.6.0" /> + <link offline="true" href="http://java.sun.com/j2ee/1.4/docs/api/" + packagelistLoc="build/javadoc/j2ee-1.4" /> + <classpath refid="classpath.javadoc" /> + </javadoc> + + <!-- Create a javadoc jar --> + <jar file="${javadoc.jar}" compress="true"> + <fileset dir="${javadoc.dir}" /> + <fileset refid="common.files.for.all.jars" /> + </jar> + + + </target> + + <target name="copy-jars"> + <delete dir="${temp.dir}" /> + <antcontrib:foreach list="${modules.to.publish.to.maven}" + target="fetch.module.and.dependencies" param="module" /> + <!-- All jars are now in temp.dir. Still need to separate vaadin + and deps --> + <move todir="${temp.deps.dir}"> + <fileset dir="${temp.dir}"> + <exclude name="vaadin-*-${vaadin.version}.*" /> + <exclude name="vaadin-*-${vaadin.version}-*.*" /> + </fileset> + </move> + + + </target> + <target name="zip" depends="copy-jars, javadoc"> + <!-- Ensure filtered webcontent files are available --> + <antcall target="common.filter.webcontent" /> + + <zip destfile="${zip.file}"> + <fileset dir="${temp.dir}"> + <!-- Avoid conflicts with servlet and portlet API. They are + provided by the container --> + <exclude name="**/servlet-api*" /> + <exclude name="**/portlet-api*" /> + <!-- Buildhelpers should not even get here ... --> + <exclude name="*buildhelpers*" /> + <!-- Zip users should not need javadoc, sources or pom files --> + <exclude name="*.pom" /> + <exclude name="*-javadoc.jar" /> + <exclude name="*-sources.jar" /> + + </fileset> + <fileset refid="common.files.for.all.jars" /> + <fileset dir="${result.dir}/.."> + <include name="README.TXT" /> + </fileset> + <!-- Do not include javadoc jar in zip as it is huge (> 40MB) + and most people do not need it. --> + </zip> + </target> + + <target name="publish-local" depends="zip"> + <antcall target="common.publish-local" /> + </target> + + <target name="clean"> + <antcall target="common.clean" /> + </target> + <target name="checkstyle"> + <!-- Checkstyle is handled by all separate modules --> + </target> + <target name="test" depends="checkstyle"> + <!-- No tests for this zip.. --> + </target> </project>
\ No newline at end of file diff --git a/all/ivy.xml b/all/ivy.xml index 2b212f6675..3c49e9a884 100644 --- a/all/ivy.xml +++ b/all/ivy.xml @@ -19,21 +19,20 @@ <!-- LIBRARY DEPENDENCIES (compile time) --> <!-- Project modules --> <dependency org="com.vaadin" name="vaadin-shared" - rev="${vaadin.version}"/> + rev="${vaadin.version}" /> <dependency org="com.vaadin" name="vaadin-server" - rev="${vaadin.version}"/> + rev="${vaadin.version}" /> <dependency org="com.vaadin" name="vaadin-client" - rev="${vaadin.version}"/> + rev="${vaadin.version}" /> <dependency org="com.vaadin" name="vaadin-client-compiler" - rev="${vaadin.version}"/> + rev="${vaadin.version}" /> <dependency org="com.vaadin" name="vaadin-theme-compiler" - rev="${vaadin.version}"/> + rev="${vaadin.version}" /> <dependency org="com.vaadin" name="vaadin-themes" - rev="${vaadin.version}"/> + rev="${vaadin.version}" /> <dependency org="com.vaadin" name="vaadin-client-compiled" - rev="${vaadin.version}"/> - <dependency org="com.vaadin" name="vaadin-push" - rev="${vaadin.version}"/> + rev="${vaadin.version}" /> + <dependency org="com.vaadin" name="vaadin-push" rev="${vaadin.version}" /> </dependencies> @@ -1,71 +1,78 @@ <?xml version="1.0"?> -<project name="vaadin" basedir="." default="package" xmlns:ivy="antlib:org.apache.ivy.ant"> - <include file="common.xml" as="common" /> +<project name="vaadin" basedir="." default="package" + xmlns:ivy="antlib:org.apache.ivy.ant"> + <include file="common.xml" as="common" /> - <path id="vaadin.buildhelpers.classpath" location="${vaadin.basedir}/buildhelpers/result/classes" /> + <path id="vaadin.buildhelpers.classpath" location="${vaadin.basedir}/buildhelpers/result/classes" /> - <!-- ================================= - target: all - ================================= --> - <!--<target name="all" description="Compiles all parts of the project" depends="buildhelpers,theme-compiler,shared,server,client">--> - <target name="package" description="Compiles and packages all modules in the project" depends="buildorder"> - <subant buildpathref="build-path" target="publish-local"> - </subant> - </target> + <!-- ================================= target: all ================================= --> + <!--<target name="all" description="Compiles all parts of the project" + depends="buildhelpers,theme-compiler,shared,server,client"> --> + <target name="package" + description="Compiles and packages all modules in the project" + depends="buildorder"> + <subant buildpathref="build-path" target="publish-local"> + </subant> + </target> - <target name="buildorder" depends="official.build.checks"> - <!-- Find out a good build order --> - <ivy:buildlist reference="ivy.build.path"> - <fileset dir="." includes="**/build.xml"> - <exclude name="build.xml" /> - <exclude name="build/**" /> - <exclude name="buildhelpers/**" /> - </fileset> - </ivy:buildlist> - <path id="build-path"> - <path location="buildhelpers/build.xml"/> - <path refid="ivy.build.path" /> - </path> - </target> - <target name="clean" depends="buildorder"> - <subant buildpathref="build-path" target="clean"> - </subant> - <delete dir="result" /> - <!-- Clean IVY cache (~/.ivy2) so no old artifacts are fetched from there (leave everything but Vaadin artifacts) --> - <delete dir="${ivy.cache.dir}/com.vaadin" /> - <delete dir="${ivy.cache.dir}/com.carrotsearch" /> + <target name="buildorder" depends="official.build.checks"> + <!-- Find out a good build order --> + <ivy:buildlist reference="ivy.build.path"> + <fileset dir="." includes="**/build.xml"> + <exclude name="build.xml" /> + <exclude name="build/**" /> + <exclude name="buildhelpers/**" /> + </fileset> + </ivy:buildlist> + <path id="build-path"> + <path location="buildhelpers/build.xml" /> + <path refid="ivy.build.path" /> + </path> + </target> + <target name="clean" depends="buildorder"> + <subant buildpathref="build-path" target="clean"> + </subant> + <delete dir="result" /> + <!-- Clean IVY cache (~/.ivy2) so no old artifacts are fetched from + there (leave everything but Vaadin artifacts) --> + <delete dir="${ivy.cache.dir}/com.vaadin" /> + <delete dir="${ivy.cache.dir}/com.carrotsearch" /> - </target> - <target name="checkstyle" depends="buildorder"> - <subant buildpathref="build-path" target="checkstyle"/> - </target> - <target name="test" depends="buildorder"> - <subant buildpathref="build-path" target="test" /> - </target> - <target name="test-all" depends="buildorder"> - <property name="war.file" location="result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${vaadin.version}.war" /> - <parallel> - <sequential> - <!-- Sleep before running integration tests so testbench tests have time to compile and start --> - <sleep minutes="4" /> - <ant antfile="uitest/integration_tests.xml" target="integration-test-all" inheritall="false" inheritrefs="false"> - <property name="demo.war" value="${war.file}" /> - </ant> - </sequential> - <subant buildpathref="build-path" target="test" /> - <ant antfile="uitest/test.xml" target="test-package"> - <property name="war.file" location="${war.file}" /> - </ant> - </parallel> - </target> + </target> + <target name="checkstyle" depends="buildorder"> + <subant buildpathref="build-path" target="checkstyle" /> + </target> + <target name="test" depends="buildorder"> + <subant buildpathref="build-path" target="test" /> + </target> + <target name="test-all" depends="buildorder"> + <property name="war.file" + location="result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${vaadin.version}.war" /> + <parallel> + <sequential> + <!-- Sleep before running integration tests so testbench + tests have time to compile and start --> + <sleep minutes="4" /> + <ant antfile="uitest/integration_tests.xml" target="integration-test-all" + inheritall="false" inheritrefs="false"> + <property name="demo.war" value="${war.file}" /> + </ant> + </sequential> + <subant buildpathref="build-path" target="test" /> + <ant antfile="uitest/test.xml" target="test-package"> + <property name="war.file" location="${war.file}" /> + </ant> + </parallel> + </target> - <target name="official.build.checks" if="build.release"> - <condition property="java.version.matches"> - <equals arg1="${ant.java.version}" arg2="${vaadin.java.version}" /> - </condition> - <fail unless="java.version.matches" message="Java version is ${ant.java.version}, but Vaadin must be compiled with genuine Java ${vaadin.java.version} compiler." /> - <echo>Java version is ${ant.java.version} as required.</echo> - </target> + <target name="official.build.checks" if="build.release"> + <condition property="java.version.matches"> + <equals arg1="${ant.java.version}" arg2="${vaadin.java.version}" /> + </condition> + <fail unless="java.version.matches" + message="Java version is ${ant.java.version}, but Vaadin must be compiled with genuine Java ${vaadin.java.version} compiler." /> + <echo>Java version is ${ant.java.version} as required.</echo> + </target> </project> diff --git a/build/common.xml b/build/common.xml index 1fc6349a46..ee60c1ff42 100644 --- a/build/common.xml +++ b/build/common.xml @@ -1,59 +1,65 @@ <?xml version="1.0"?> <project xmlns:antcontrib="antlib:net.sf.antcontrib" - xmlns:artifact="antlib:org.apache.maven.artifact.ant" - xmlns:ivy="antlib:org.apache.ivy.ant" - name="common" - basedir="../" - default="init-deps" > - - <property name="ivy.install.version" value="2.2.0"/> - <property name="ivy.jar.name" value="ivy-${ivy.install.version}.jar"/> + xmlns:artifact="antlib:org.apache.maven.artifact.ant" xmlns:ivy="antlib:org.apache.ivy.ant" + name="common" basedir="../" default="init-deps"> + + <property name="ivy.install.version" value="2.2.0" /> + <property name="ivy.jar.name" value="ivy-${ivy.install.version}.jar" /> <property name="ivy.jar.dir" value="${user.home}/.ant/lib" /> <property name="ivy.jar.file" value="${ivy.jar.dir}/${ivy.jar.name}" /> - - <target name="init-deps" description="Configure Ivy dependency management and load common task definitions" - depends="init-taskdefs" unless="deps.initialized"> + + <target name="init-deps" + description="Configure Ivy dependency management and load common task definitions" + depends="init-taskdefs" unless="deps.initialized"> <property name="deps.initialized" value="1" /> </target> - + <target name="check-ivy-installed"> - <available property="ivy.installed" file="${ivy.jar.file}"/> - <available property="ivy.installed" classname="org.apache.ivy.ant.IvyConfigure" /> - <antcall target="common.ivy-download" /> - </target> + <available property="ivy.installed" file="${ivy.jar.file}" /> + <available property="ivy.installed" classname="org.apache.ivy.ant.IvyConfigure" /> + <antcall target="common.ivy-download" /> + </target> <target name="ivy-download" unless="ivy.installed"> - <mkdir dir="${ivy.jar.dir}"/> - <get src="http://repo2.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar" dest="${ivy.jar.file}" usetimestamp="true"/> + <mkdir dir="${ivy.jar.dir}" /> + <get + src="http://repo2.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar" + dest="${ivy.jar.file}" usetimestamp="true" /> + </target> + + <target name="ivy-configure" depends="check-ivy-installed" + unless="deps.initialized"> + <!-- Ivy task definitions --> + <taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" + classpath="${ivy.jar.file}" /> + <!-- Ivy settings --> + <property name="ivy.settings.file" + value="${project.root}/build/ivy/ivysettings.xml" /> + <ivy:configure /> </target> - <target name="ivy-configure" depends="check-ivy-installed" unless="deps.initialized"> - <!-- Ivy task definitions --> - <taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpath="${ivy.jar.file}" /> - <!-- Ivy settings --> - <property name="ivy.settings.file" value="${project.root}/build/ivy/ivysettings.xml" /> - <ivy:configure/> - </target> - <target name="init-taskdefs" depends="ivy-configure" unless="deps.initialized"> <echo>Loading Ant tasks</echo> - <ivy:resolve file="${project.root}/build/ivy/ivy.xml" conf="taskdefs" /> + <ivy:resolve file="${project.root}/build/ivy/ivy.xml" + conf="taskdefs" /> <ivy:cachepath pathid="taskdefs.classpath" conf="taskdefs" /> - <taskdef resource="emma_ant.properties" classpathref="taskdefs.classpath" /> - - <!-- ant contrib required for flow control (for loop, if, property override) --> - <!-- Note that we have to use a namespace to avoid clash when running sub-ant. --> + <taskdef resource="emma_ant.properties" classpathref="taskdefs.classpath" /> + + <!-- ant contrib required for flow control (for loop, if, property + override) --> + <!-- Note that we have to use a namespace to avoid clash when running + sub-ant. --> <taskdef uri="antlib:net.sf.antcontrib" resource="net/sf/antcontrib/antlib.xml" classpathref="taskdefs.classpath" /> - - <!-- ant contrib for Maven integration --> + + <!-- ant contrib for Maven integration --> <taskdef resource="org/apache/maven/artifact/ant/antlib.xml" - uri="antlib:org.apache.maven.artifact.ant" classpathref="taskdefs.classpath" /> - - <!-- jarjar --> + uri="antlib:org.apache.maven.artifact.ant" classpathref="taskdefs.classpath" /> + + <!-- jarjar --> <taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" - classpathref="taskdefs.classpath"/> + classpathref="taskdefs.classpath" /> </target> diff --git a/build/ide.xml b/build/ide.xml index b1845020f3..5380536e2e 100755 --- a/build/ide.xml +++ b/build/ide.xml @@ -1,152 +1,165 @@ <?xml version="1.0"?> -<project xmlns:antcontrib="antlib:net.sf.antcontrib" xmlns:artifact="antlib:org.apache.maven.artifact.ant" xmlns:ivy="antlib:org.apache.ivy.ant" name="Build script for IDE users" basedir=".." default="theme-and-default-widgetset"> - <include file="${basedir}/gwt-files.xml" /> - - <property name="gwt.dev.classes" location="${gwt.eclipse.basedir}/dev/bin" /> - <property name="gwt.user.classes" location="${gwt.eclipse.basedir}/user/bin" /> - <property name="gwt.dev.src" location="${gwt.basedir}/dev/core/src" /> - <property name="gwt.dev.super.src" location="${gwt.basedir}/dev/core/super" /> - <property name="gwt.user.src" location="${gwt.basedir}/user/src" /> - <property name="gwt.user.super.src" location="${gwt.basedir}/user/super" /> - - <property name="work.dir" location="work" /> - <property name="theme-version" location="9.9.9.INTERNAL-DEBUG-BUILD" /> - <echo>Using gwt files from ${gwt.user.classes} and ${gwt.dev.classes}</echo> - - <ivy:resolve file="client-compiler/ivy.xml" conf="ide" /> - <ivy:cachepath pathid="client-compiler.deps" conf="ide" /> - <ivy:resolve file="server/ivy.xml" conf="ide" /> - <ivy:cachepath pathid="server.deps" conf="ide" /> - <ivy:resolve file="client/ivy.xml" conf="ide" /> - <ivy:cachepath pathid="client.deps" conf="ide" /> - <ivy:resolve file="shared/ivy.xml" conf="ide" /> - <ivy:cachepath pathid="shared.deps" conf="ide" /> - <ivy:resolve file="uitest/ivy.xml" conf="ide" /> - <ivy:cachepath pathid="uitest.deps" conf="ide" /> - <ivy:resolve file="theme-compiler/ivy.xml" conf="ide" /> - <ivy:cachepath pathid="theme-compiler.deps" conf="ide" /> - - <path id="classpath"> - <path location="bin" /> - <path location="build/classes" /> - <path location="${gwt.user.classes}" /> - <path location="${gwt.user.src}" /> - <path location="${gwt.user.super.src}" /> - <path location="${gwt.dev.classes}" /> - <path location="${gwt.dev.super.src}" /> - <path location="${gwt.dev.src}" /> - <path refid="client-compiler.deps" /> - <path refid="theme-compiler.deps" /> - <path refid="server.deps" /> - <path refid="shared.deps" /> - <path refid="uitest.deps" /> - <path refid="client.deps" /> - <path location="theme-compiler/src" /> - <path location="server/src" /> - <path location="shared/src" /> - <path location="uitest/src" /> - <path location="client/src" /> - </path> - - <target name="theme-and-default-widgetset" depends="default-widgetset, themes, vaadinPush.js"> - </target> - <target name="themes"> - <antcall target="compile-theme"> - <param name="theme" value="base" /> - </antcall> - <antcall target="compile-theme"> - <param name="theme" value="runo" /> - </antcall> - <antcall target="compile-theme"> - <param name="theme" value="reindeer" /> - </antcall> - <antcall target="compile-theme"> - <param name="theme" value="chameleon" /> - </antcall> - <antcall target="compile-theme"> - <param name="theme" value="liferay" /> - </antcall> - </target> - - <target name="compile-theme"> - <java classname="com.vaadin.buildhelpers.CompileTheme" failonerror="yes" fork="yes"> - <classpath refid="classpath" /> - <jvmarg value="-Djava.awt.headless=true" /> - <arg value="--theme" /> - <arg value="${theme}" /> - <arg value="--theme-version" /> - <arg value="${theme-version}" /> - <arg value="--theme-folder" /> - <arg value="WebContent/VAADIN/themes" /> - </java> - - </target> - - - <target name="default-widgetset"> - <antcall target="compile-widgetset"> - <param name="widgetset" value="com.vaadin.DefaultWidgetSet" /> - </antcall> - </target> - - <target name="testing-widgetset"> - <antcall target="compile-widgetset"> - <param name="widgetset" value="com.vaadin.tests.widgetset.TestingWidgetSet" /> - </antcall> - </target> - - <target name="compile-widgetset"> - <property name="module" value="${widgetset}" /> - <property name="module.output.dir" location="WebContent/VAADIN/widgetsets" /> - <property name="style" value="PRETTY" /> - <property name="localWorkers" value="2" /> - <property name="extraParams" value="" /> - - <mkdir dir="${module.output.dir}" /> - - <echo>Compiling ${module} to ${module.output.dir} with parameters -logLevel TRACE -style ${style} -localWorkers ${localWorkers} -strict ${extraParams}</echo> - - <!--<ivy:resolve inline="true" organisation="javax.validation" module="validation-api" revision="1.0.0.GA"/>--> - - <!-- compile the module --> - <java classname="com.google.gwt.dev.Compiler" classpathref="classpath" failonerror="yes" fork="yes" maxmemory="512m"> - <arg value="-workDir" /> - <arg value="${work.dir}" /> - <arg value="-logLevel" /> - <arg value="TRACE" /> - <arg value="-war" /> - <arg value="${module.output.dir}" /> - <arg value="-style" /> - <arg value="${style}" /> - - <arg value="-localWorkers" /> - <arg value="${localWorkers}" /> - <arg value="-strict" /> - <arg line="${extraParams}" /> - <arg value="${module}" /> - - <sysproperty key="vFailIfNotSerializable" value="true" /> - - <jvmarg value="-Xss8M" /> - <jvmarg value="-XX:MaxPermSize=256M" /> - <jvmarg value="-Djava.awt.headless=true" /> - <jvmarg value="-Dgwt.usearchives=false" /> - </java> - </target> - <target name="vaadinPush.js"> - <property name="vaadinPush.js.output" location="WebContent/VAADIN/vaadinPush.js" /> - - <loadfile srcfile="WebContent/VAADIN/jquery-1.7.2.js" property="jquery.js.contents" /> - <loadfile srcfile="WebContent/VAADIN/jquery.atmosphere.js" property="jquery.atmosphere.js.contents" /> - <loadfile srcfile="WebContent/VAADIN/vaadinPush.js.tpl" property="vaadinPush.js.contents"> - <filterchain> - <replacetokens begintoken="@" endtoken="@"> - <token key="jquery.js" value="${jquery.js.contents}" /> - <token key="jquery.atmosphere.js" value="${jquery.atmosphere.js.contents}" /> - </replacetokens> - </filterchain> - </loadfile> - <echo file="${vaadinPush.js.output}">${vaadinPush.js.contents}</echo> - </target> +<project xmlns:antcontrib="antlib:net.sf.antcontrib" + xmlns:artifact="antlib:org.apache.maven.artifact.ant" xmlns:ivy="antlib:org.apache.ivy.ant" + name="Build script for IDE users" basedir=".." + default="theme-and-default-widgetset"> + <include file="${basedir}/gwt-files.xml" /> + + <property name="gwt.dev.classes" location="${gwt.eclipse.basedir}/dev/bin" /> + <property name="gwt.user.classes" location="${gwt.eclipse.basedir}/user/bin" /> + <property name="gwt.dev.src" location="${gwt.basedir}/dev/core/src" /> + <property name="gwt.dev.super.src" location="${gwt.basedir}/dev/core/super" /> + <property name="gwt.user.src" location="${gwt.basedir}/user/src" /> + <property name="gwt.user.super.src" location="${gwt.basedir}/user/super" /> + + <property name="work.dir" location="work" /> + <property name="theme-version" location="9.9.9.INTERNAL-DEBUG-BUILD" /> + <echo>Using gwt files from ${gwt.user.classes} and + ${gwt.dev.classes}</echo> + + <ivy:resolve file="client-compiler/ivy.xml" conf="ide" /> + <ivy:cachepath pathid="client-compiler.deps" conf="ide" /> + <ivy:resolve file="server/ivy.xml" conf="ide" /> + <ivy:cachepath pathid="server.deps" conf="ide" /> + <ivy:resolve file="client/ivy.xml" conf="ide" /> + <ivy:cachepath pathid="client.deps" conf="ide" /> + <ivy:resolve file="shared/ivy.xml" conf="ide" /> + <ivy:cachepath pathid="shared.deps" conf="ide" /> + <ivy:resolve file="uitest/ivy.xml" conf="ide" /> + <ivy:cachepath pathid="uitest.deps" conf="ide" /> + <ivy:resolve file="theme-compiler/ivy.xml" conf="ide" /> + <ivy:cachepath pathid="theme-compiler.deps" conf="ide" /> + + <path id="classpath"> + <path location="bin" /> + <path location="build/classes" /> + <path location="${gwt.user.classes}" /> + <path location="${gwt.user.src}" /> + <path location="${gwt.user.super.src}" /> + <path location="${gwt.dev.classes}" /> + <path location="${gwt.dev.super.src}" /> + <path location="${gwt.dev.src}" /> + <path refid="client-compiler.deps" /> + <path refid="theme-compiler.deps" /> + <path refid="server.deps" /> + <path refid="shared.deps" /> + <path refid="uitest.deps" /> + <path refid="client.deps" /> + <path location="theme-compiler/src" /> + <path location="server/src" /> + <path location="shared/src" /> + <path location="uitest/src" /> + <path location="client/src" /> + </path> + + <target name="theme-and-default-widgetset" depends="default-widgetset, themes, vaadinPush.js"> + </target> + <target name="themes"> + <antcall target="compile-theme"> + <param name="theme" value="base" /> + </antcall> + <antcall target="compile-theme"> + <param name="theme" value="runo" /> + </antcall> + <antcall target="compile-theme"> + <param name="theme" value="reindeer" /> + </antcall> + <antcall target="compile-theme"> + <param name="theme" value="chameleon" /> + </antcall> + <antcall target="compile-theme"> + <param name="theme" value="liferay" /> + </antcall> + </target> + + <target name="compile-theme"> + <java classname="com.vaadin.buildhelpers.CompileTheme" + failonerror="yes" fork="yes"> + <classpath refid="classpath" /> + <jvmarg value="-Djava.awt.headless=true" /> + <arg value="--theme" /> + <arg value="${theme}" /> + <arg value="--theme-version" /> + <arg value="${theme-version}" /> + <arg value="--theme-folder" /> + <arg value="WebContent/VAADIN/themes" /> + </java> + + </target> + + + <target name="default-widgetset"> + <antcall target="compile-widgetset"> + <param name="widgetset" value="com.vaadin.DefaultWidgetSet" /> + </antcall> + </target> + + <target name="testing-widgetset"> + <antcall target="compile-widgetset"> + <param name="widgetset" + value="com.vaadin.tests.widgetset.TestingWidgetSet" /> + </antcall> + </target> + + <target name="compile-widgetset"> + <property name="module" value="${widgetset}" /> + <property name="module.output.dir" location="WebContent/VAADIN/widgetsets" /> + <property name="style" value="PRETTY" /> + <property name="localWorkers" value="2" /> + <property name="extraParams" value="" /> + + <mkdir dir="${module.output.dir}" /> + + <echo>Compiling ${module} to ${module.output.dir} with + parameters -logLevel TRACE -style ${style} -localWorkers + ${localWorkers} -strict ${extraParams}</echo> + + <!--<ivy:resolve inline="true" organisation="javax.validation" module="validation-api" + revision="1.0.0.GA"/> --> + + <!-- compile the module --> + <java classname="com.google.gwt.dev.Compiler" classpathref="classpath" + failonerror="yes" fork="yes" maxmemory="512m"> + <arg value="-workDir" /> + <arg value="${work.dir}" /> + <arg value="-logLevel" /> + <arg value="TRACE" /> + <arg value="-war" /> + <arg value="${module.output.dir}" /> + <arg value="-style" /> + <arg value="${style}" /> + + <arg value="-localWorkers" /> + <arg value="${localWorkers}" /> + <arg value="-strict" /> + <arg line="${extraParams}" /> + <arg value="${module}" /> + + <sysproperty key="vFailIfNotSerializable" value="true" /> + + <jvmarg value="-Xss8M" /> + <jvmarg value="-XX:MaxPermSize=256M" /> + <jvmarg value="-Djava.awt.headless=true" /> + <jvmarg value="-Dgwt.usearchives=false" /> + </java> + </target> + <target name="vaadinPush.js"> + <property name="vaadinPush.js.output" location="WebContent/VAADIN/vaadinPush.js" /> + + <loadfile srcfile="WebContent/VAADIN/jquery-1.7.2.js" + property="jquery.js.contents" /> + <loadfile srcfile="WebContent/VAADIN/jquery.atmosphere.js" + property="jquery.atmosphere.js.contents" /> + <loadfile srcfile="WebContent/VAADIN/vaadinPush.js.tpl" + property="vaadinPush.js.contents"> + <filterchain> + <replacetokens begintoken="@" endtoken="@"> + <token key="jquery.js" value="${jquery.js.contents}" /> + <token key="jquery.atmosphere.js" value="${jquery.atmosphere.js.contents}" /> + </replacetokens> + </filterchain> + </loadfile> + <echo file="${vaadinPush.js.output}">${vaadinPush.js.contents}</echo> + </target> </project>
\ No newline at end of file diff --git a/buildhelpers/build.xml b/buildhelpers/build.xml index a101bff191..aa1eb8cb0d 100644 --- a/buildhelpers/build.xml +++ b/buildhelpers/build.xml @@ -1,50 +1,51 @@ <?xml version="1.0"?> <project name="vaadin-buildhelpers" basedir="." default="publish-local"> - <description> - Compiles build helpers used when building other modules. - </description> - <include file="../build.xml" as="vaadin" /> - <include file="../common.xml" as="common" /> - - <property name="module.name" value="vaadin-buildhelpers" /> - <property name="module.symbolic" value="com.vaadin.buildhelpers" /> - <property name="result.dir" location="result" /> - <path id="classpath.compile.custom" /> - - <target name="jar"> - <antcall target="common.jar"> - <reference torefid="extra.jar.includes" refid="empty.reference" /> - </antcall> - </target> - - <target name="publish-local" depends="jar"> - <antcall target="common.sources.jar"> - <reference torefid="extra.jar.includes" refid="empty.reference" /> - </antcall> - <antcall target="common.javadoc.jar" /> - <antcall target="common.publish-local" /> - </target> - - <target name="clean"> - <antcall target="common.clean" /> - </target> - - <target name="checkstyle"> - <antcall target="common.checkstyle"> - <param name="cs.src" location="src" /> - </antcall> - </target> - - <target name="fetch-release-notes-tickets"> - <antcall target="common.exec-buildhelper"> - <param name="main.class" value="com.vaadin.buildhelpers.FetchReleaseNotesTickets" /> - <param name="output" value="${output}" /> - </antcall> - </target> - - <target name="test" depends="checkstyle"> - <!--<antcall target="common.test.run" />--> - <echo>WHAT? No JUnit tests for ${module.name}!</echo> - </target> + <description> + Compiles build helpers used when building other modules. + </description> + <include file="../build.xml" as="vaadin" /> + <include file="../common.xml" as="common" /> + + <property name="module.name" value="vaadin-buildhelpers" /> + <property name="module.symbolic" value="com.vaadin.buildhelpers" /> + <property name="result.dir" location="result" /> + <path id="classpath.compile.custom" /> + + <target name="jar"> + <antcall target="common.jar"> + <reference torefid="extra.jar.includes" refid="empty.reference" /> + </antcall> + </target> + + <target name="publish-local" depends="jar"> + <antcall target="common.sources.jar"> + <reference torefid="extra.jar.includes" refid="empty.reference" /> + </antcall> + <antcall target="common.javadoc.jar" /> + <antcall target="common.publish-local" /> + </target> + + <target name="clean"> + <antcall target="common.clean" /> + </target> + + <target name="checkstyle"> + <antcall target="common.checkstyle"> + <param name="cs.src" location="src" /> + </antcall> + </target> + + <target name="fetch-release-notes-tickets"> + <antcall target="common.exec-buildhelper"> + <param name="main.class" + value="com.vaadin.buildhelpers.FetchReleaseNotesTickets" /> + <param name="output" value="${output}" /> + </antcall> + </target> + + <target name="test" depends="checkstyle"> + <!--<antcall target="common.test.run" /> --> + <echo>WHAT? No JUnit tests for ${module.name}!</echo> + </target> </project>
\ No newline at end of file diff --git a/buildhelpers/ivy.xml b/buildhelpers/ivy.xml index 7c0a7b82a7..21c2a808cc 100644 --- a/buildhelpers/ivy.xml +++ b/buildhelpers/ivy.xml @@ -28,7 +28,7 @@ </publications> <dependencies> - <dependency org="commons-io" name="commons-io" rev="2.2" /> + <dependency org="commons-io" name="commons-io" rev="2.2" /> </dependencies> </ivy-module> diff --git a/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java b/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java index 588fe1aba1..5c3810099a 100644 --- a/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java +++ b/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java @@ -46,8 +46,15 @@ public class FetchReleaseNotesTickets { // This is the header continue; } + String summary = fields[1]; + if (summary.startsWith("\"") && summary.endsWith("\"")) { + // If a summary starts with " and ends with " then all quotes in + // the summary are encoded as double quotes + summary = summary.substring(1, summary.length() - 1); + summary = summary.replace("\"\"", "\""); + } System.out.println(ticketTemplate.replace("@ticket@", fields[0]) - .replace("@description@", fields[1])); + .replace("@description@", summary)); } urlStream.close(); } diff --git a/client-compiled/build.xml b/client-compiled/build.xml index c9c3244c0e..01bf2fa15e 100644 --- a/client-compiled/build.xml +++ b/client-compiled/build.xml @@ -1,139 +1,149 @@ <?xml version="1.0"?> -<project name="vaadin-client-compiled" basedir="." default="publish-local" xmlns:ivy="antlib:org.apache.ivy.ant"> - <description> - Compiled (JS+HTML) version of client side - </description> - - <include file="../common.xml" as="common" /> - <include file="../build.xml" as="vaadin" /> - <include file="../gwt-files.xml" as="gwtfiles" /> - - <!-- global properties --> - <property name="module.name" value="vaadin-client-compiled" /> - <property name="module.symbolic" value="com.vaadin.client-compiled" /> - <property name="result.dir" value="result" /> - <property name="gwtar.dir" location="${result.dir}/gwtar" /> - <property name="work.dir" location="${result.dir}/work" /> - <property name="module.output.dir" location="${result.dir}/VAADIN/widgetsets" /> - <property name="compiled.jar" location="${result.dir}/lib/${module.name}-${vaadin.version}.jar" /> - <property name="compiled-cache.jar" location="${result.dir}/lib/${module.name}-cache-${vaadin.version}.jar" /> - - <union id="jar.includes"> - <fileset dir="${result.dir}"> - <include name="VAADIN/widgetsets/com.vaadin*/**" /> - </fileset> - </union> - - <target name="default-widgetset-cache"> - <antcall target="compile-module-cache"> - <param name="module" value="com.vaadin.DefaultWidgetSet" /> - </antcall> - </target> - - <target name="default-widgetset"> - <antcall target="compile-module"> - <param name="module" value="com.vaadin.DefaultWidgetSet" /> - </antcall> - </target> - - - <target name="compile-module-cache"> - <fail unless="module" message="You must give the module to compile in the 'module' parameter" /> - <ivy:resolve resolveid="common" conf="compile-module" /> - <ivy:cachepath pathid="classpath.compile.widgetset" conf="compile-module" /> - <echo>Creating gwtar files for ${module} in ${gwtar.dir}</echo> - - <!-- Produce gwtar files for the separate JAR --> - <java classname="com.google.gwt.dev.CompileModule" classpathref="classpath.compile.widgetset" failonerror="yes" fork="yes" maxmemory="512m"> - <arg value="-out" /> - <arg value="${gwtar.dir}" /> - <arg value="-strict" /> - <arg value="${module}" /> - - <jvmarg value="-Xss8M" /> - <jvmarg value="-XX:MaxPermSize=256M" /> - <jvmarg value="-Djava.awt.headless=true" /> - </java> - </target> - - <target name="compile-module"> - <fail unless="module" message="You must give the module to compile in the 'module' parameter" /> - <property name="style" value="OBF" /> - <property name="localWorkers" value="2" /> - <property name="extraParams" value="" /> - - <ivy:resolve resolveid="common" conf="compile-module" /> - <ivy:cachepath pathid="classpath.compile.widgetset" conf="compile-module" /> - - <mkdir dir="${module.output.dir}" /> - - <echo>Compiling ${module} to ${module.output.dir}</echo> - - <!-- compile the module --> - <java classname="com.google.gwt.dev.Compiler" classpathref="classpath.compile.widgetset" failonerror="yes" fork="yes" maxmemory="512m"> - <classpath location="${compiled-cache.jar}" /> - <arg value="-workDir" /> - <arg value="${work.dir}" /> - <arg value="-logLevel" /> - <arg value="TRACE" /> - <arg value="-war" /> - <arg value="${module.output.dir}" /> - <arg value="-style" /> - <arg value="${style}" /> - - <arg value="-localWorkers" /> - <arg value="${localWorkers}" /> - <arg value="-strict" /> - <arg value="-XenableClosureCompiler" /> - <arg line="${extraParams}" /> - <arg value="${module}" /> - - <sysproperty key="vFailIfNotSerializable" value="true" /> - - <jvmarg value="-Xss8M" /> - <jvmarg value="-XX:MaxPermSize=256M" /> - <jvmarg value="-Djava.awt.headless=true" /> - </java> - - </target> - - <target name="client-compiled-cache.jar" depends="default-widgetset-cache"> - <!-- Ensure filtered webcontent files are available --> - <antcall target="common.filter.webcontent" /> - - <jar file="${compiled-cache.jar}" compress="true"> - <fileset dir="${gwtar.dir}"> - <include name="**/*.gwtar" /> - </fileset> - <union refid="client-compiled-cache.gwt.includes" /> - <fileset refid="common.files.for.all.jars" /> - </jar> - </target> - - <target name="jar" depends="default-widgetset"> - <antcall target="common.jar"> - <param name="osgi.extra.package.prefixes" value="VAADIN/widgetsets/" /> - <reference torefid="extra.jar.includes" refid="jar.includes" /> - </antcall> - </target> - - <target name="publish-local" depends="jar"> - <antcall target="common.publish-local"> - <param name="conf" value="build" /> - </antcall> - </target> - - <target name="clean"> - <antcall target="common.clean" /> - </target> - - <target name="checkstyle"> - <echo>No java files in module</echo> - </target> - <target name="test" depends="checkstyle"> - <!--<antcall target="common.test.run" />--> - <echo>WHAT? No tests for ${module.name}!</echo> - </target> +<project name="vaadin-client-compiled" basedir="." default="publish-local" + xmlns:ivy="antlib:org.apache.ivy.ant"> + <description> + Compiled (JS+HTML) version of client side + </description> + + <include file="../common.xml" as="common" /> + <include file="../build.xml" as="vaadin" /> + <include file="../gwt-files.xml" as="gwtfiles" /> + + <!-- global properties --> + <property name="module.name" value="vaadin-client-compiled" /> + <property name="module.symbolic" value="com.vaadin.client-compiled" /> + <property name="result.dir" value="result" /> + <property name="gwtar.dir" location="${result.dir}/gwtar" /> + <property name="work.dir" location="${result.dir}/work" /> + <property name="module.output.dir" location="${result.dir}/VAADIN/widgetsets" /> + <property name="compiled.jar" + location="${result.dir}/lib/${module.name}-${vaadin.version}.jar" /> + <property name="compiled-cache.jar" + location="${result.dir}/lib/${module.name}-cache-${vaadin.version}.jar" /> + + <union id="jar.includes"> + <fileset dir="${result.dir}"> + <include name="VAADIN/widgetsets/com.vaadin*/**" /> + </fileset> + </union> + + <target name="default-widgetset-cache"> + <antcall target="compile-module-cache"> + <param name="module" value="com.vaadin.DefaultWidgetSet" /> + </antcall> + </target> + + <target name="default-widgetset"> + <antcall target="compile-module"> + <param name="module" value="com.vaadin.DefaultWidgetSet" /> + </antcall> + </target> + + + <target name="compile-module-cache"> + <fail unless="module" + message="You must give the module to compile in the 'module' parameter" /> + <ivy:resolve resolveid="common" conf="compile-module" /> + <ivy:cachepath pathid="classpath.compile.widgetset" + conf="compile-module" /> + <echo>Creating gwtar files for ${module} in ${gwtar.dir}</echo> + + <!-- Produce gwtar files for the separate JAR --> + <java classname="com.google.gwt.dev.CompileModule" + classpathref="classpath.compile.widgetset" failonerror="yes" + fork="yes" maxmemory="512m"> + <arg value="-out" /> + <arg value="${gwtar.dir}" /> + <arg value="-strict" /> + <arg value="${module}" /> + + <jvmarg value="-Xss8M" /> + <jvmarg value="-XX:MaxPermSize=256M" /> + <jvmarg value="-Djava.awt.headless=true" /> + </java> + </target> + + <target name="compile-module"> + <fail unless="module" + message="You must give the module to compile in the 'module' parameter" /> + <property name="style" value="OBF" /> + <property name="localWorkers" value="2" /> + <property name="extraParams" value="" /> + + <ivy:resolve resolveid="common" conf="compile-module" /> + <ivy:cachepath pathid="classpath.compile.widgetset" + conf="compile-module" /> + + <mkdir dir="${module.output.dir}" /> + + <echo>Compiling ${module} to ${module.output.dir}</echo> + + <!-- compile the module --> + <java classname="com.google.gwt.dev.Compiler" classpathref="classpath.compile.widgetset" + failonerror="yes" fork="yes" maxmemory="512m"> + <classpath location="${compiled-cache.jar}" /> + <arg value="-workDir" /> + <arg value="${work.dir}" /> + <arg value="-logLevel" /> + <arg value="TRACE" /> + <arg value="-war" /> + <arg value="${module.output.dir}" /> + <arg value="-style" /> + <arg value="${style}" /> + + <arg value="-localWorkers" /> + <arg value="${localWorkers}" /> + <arg value="-strict" /> + <arg value="-XenableClosureCompiler" /> + <arg line="${extraParams}" /> + <arg value="${module}" /> + + <sysproperty key="vFailIfNotSerializable" value="true" /> + + <jvmarg value="-Xss8M" /> + <jvmarg value="-XX:MaxPermSize=256M" /> + <jvmarg value="-Djava.awt.headless=true" /> + </java> + + </target> + + <target name="client-compiled-cache.jar" depends="default-widgetset-cache"> + <!-- Ensure filtered webcontent files are available --> + <antcall target="common.filter.webcontent" /> + + <jar file="${compiled-cache.jar}" compress="true"> + <fileset dir="${gwtar.dir}"> + <include name="**/*.gwtar" /> + </fileset> + <union refid="client-compiled-cache.gwt.includes" /> + <fileset refid="common.files.for.all.jars" /> + </jar> + </target> + + <target name="jar" depends="default-widgetset"> + <antcall target="common.jar"> + <param name="osgi.extra.package.prefixes" value="VAADIN/widgetsets/" /> + <reference torefid="extra.jar.includes" refid="jar.includes" /> + </antcall> + </target> + + <target name="publish-local" depends="jar"> + <antcall target="common.publish-local"> + <param name="conf" value="build" /> + </antcall> + </target> + + <target name="clean"> + <antcall target="common.clean" /> + </target> + + <target name="checkstyle"> + <echo>No java files in module</echo> + </target> + <target name="test" depends="checkstyle"> + <!--<antcall target="common.test.run" /> --> + <echo>WHAT? No tests for ${module.name}!</echo> + </target> </project> diff --git a/client-compiled/ivy.xml b/client-compiled/ivy.xml index 7802775f70..2f1dcfd22f 100644 --- a/client-compiled/ivy.xml +++ b/client-compiled/ivy.xml @@ -14,8 +14,8 @@ </configurations> <publications> <artifact type="jar" ext="jar" /> -<!-- <artifact type="source" ext="jar" m:classifier="sources" /> --> -<!-- <artifact type="javadoc" ext="jar" m:classifier="javadoc" /> --> + <!-- <artifact type="source" ext="jar" m:classifier="sources" /> --> + <!-- <artifact type="javadoc" ext="jar" m:classifier="javadoc" /> --> <artifact type="pom" ext="pom" /> <!-- cache must be a separate artifact, not within vaadin-client-compiled --> <!-- <artifact type="jar" name="vaadin-client-compiled-cache"/> --> diff --git a/client-compiler/build.xml b/client-compiler/build.xml index cd8433f1cf..0ed4d7b0e3 100644 --- a/client-compiler/build.xml +++ b/client-compiler/build.xml @@ -1,68 +1,70 @@ <?xml version="1.0"?> -<project name="vaadin-client-compiler" basedir="." default="publish-local" xmlns:ivy="antlib:org.apache.ivy.ant"> - <description> - Compiles build helpers used when building other modules. - </description> - <include file="../common.xml" as="common" /> - <include file="../build.xml" as="vaadin" /> - <include file="../gwt-files.xml" as="gwtfiles" /> +<project name="vaadin-client-compiler" basedir="." default="publish-local" + xmlns:ivy="antlib:org.apache.ivy.ant"> + <description> + Compiles build helpers used when building other modules. + </description> + <include file="../common.xml" as="common" /> + <include file="../build.xml" as="vaadin" /> + <include file="../gwt-files.xml" as="gwtfiles" /> - <!-- global properties --> - <property name="module.name" value="vaadin-client-compiler" /> - <property name="module.symbolic" value="com.vaadin.client-compiler" /> - <property name="result.dir" value="result" /> - <path id="classpath.compile.custom"> - <fileset file="${gwt.dev.jar}" /> - </path> + <!-- global properties --> + <property name="module.name" value="vaadin-client-compiler" /> + <property name="module.symbolic" value="com.vaadin.client-compiler" /> + <property name="result.dir" value="result" /> + <path id="classpath.compile.custom"> + <fileset file="${gwt.dev.jar}" /> + </path> - <union id="compiler.includes"> - <union refid="client-compiler.gwt.includes" /> - <fileset dir="${result.dir}"> - <include name="com/google/gwt/dev/About.properties" /> - </fileset> - </union> + <union id="compiler.includes"> + <union refid="client-compiler.gwt.includes" /> + <fileset dir="${result.dir}"> + <include name="com/google/gwt/dev/About.properties" /> + </fileset> + </union> - <target name="jar"> - <!-- Get Git revision --> - <exec executable="git" outputproperty="git.revision" failifexecutionfails="false" errorproperty=""> - <arg value="describe" /> - <arg value="--tags" /> - <arg value="--always" /> - <arg value="HEAD" /> - </exec> + <target name="jar"> + <!-- Get Git revision --> + <exec executable="git" outputproperty="git.revision" + failifexecutionfails="false" errorproperty=""> + <arg value="describe" /> + <arg value="--tags" /> + <arg value="--always" /> + <arg value="HEAD" /> + </exec> - <echo file="${result.dir}/com/google/gwt/dev/About.properties">gwt.version=${vaadin.version} -gwt.svnrev=${git.revision}</echo> + <echo file="${result.dir}/com/google/gwt/dev/About.properties">gwt.version=${vaadin.version} + gwt.svnrev=${git.revision}</echo> - <antcall target="common.jar"> - <reference refid="compiler.includes" torefid="extra.jar.includes" /> - </antcall> + <antcall target="common.jar"> + <reference refid="compiler.includes" torefid="extra.jar.includes" /> + </antcall> - </target> + </target> - <target name="publish-local" depends="jar"> - <antcall target="common.sources.jar"> - <reference torefid="extra.jar.includes" refid="compiler.includes" /> - </antcall> - <antcall target="common.javadoc.jar" /> + <target name="publish-local" depends="jar"> + <antcall target="common.sources.jar"> + <reference torefid="extra.jar.includes" refid="compiler.includes" /> + </antcall> + <antcall target="common.javadoc.jar" /> - <antcall target="common.publish-local" /> - </target> + <antcall target="common.publish-local" /> + </target> - <target name="clean"> - <antcall target="common.clean" /> - </target> + <target name="clean"> + <antcall target="common.clean" /> + </target> - <target name="checkstyle"> - <antcall target="common.checkstyle"> - <param name="cs.src" location="src" /> - </antcall> - </target> + <target name="checkstyle"> + <antcall target="common.checkstyle"> + <param name="cs.src" location="src" /> + </antcall> + </target> - <target name="test" depends="checkstyle"> - <!--<antcall target="common.test.run" />--> - <echo>WHAT? No tests for ${module.name}!</echo> - </target> + <target name="test" depends="checkstyle"> + <!--<antcall target="common.test.run" /> --> + <echo>WHAT? No tests for ${module.name}!</echo> + </target> </project>
\ No newline at end of file diff --git a/client-compiler/ivy.xml b/client-compiler/ivy.xml index b26de51aca..f66a2e0255 100644 --- a/client-compiler/ivy.xml +++ b/client-compiler/ivy.xml @@ -1,62 +1,64 @@ <?xml version="1.0" encoding="UTF-8"?> <ivy-module version="2.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd" - xmlns:m="http://ant.apache.org/ivy/maven"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd" + xmlns:m="http://ant.apache.org/ivy/maven"> - <info organisation="com.vaadin" module="vaadin-client-compiler" - revision="${vaadin.version}" /> + <info organisation="com.vaadin" module="vaadin-client-compiler" + revision="${vaadin.version}" /> - <configurations> - <conf name="build" /> - <conf name="build-provided" /> - <conf name="ide" visibility="private" /> - </configurations> - <publications> - <artifact type="jar" ext="jar" /> - <artifact type="source" ext="jar" m:classifier="sources" /> - <artifact type="javadoc" ext="jar" m:classifier="javadoc" /> - <artifact type="pom" ext="pom" /> - </publications> - <dependencies> - <dependency org="com.vaadin" name="vaadin-shared" rev="${vaadin.version}" - conf="build" /> - <dependency org="com.vaadin" name="vaadin-server" rev="${vaadin.version}" - conf="build" /> - <dependency org="com.vaadin" name="vaadin-client" rev="${vaadin.version}" - conf="build" /> - <dependency org="com.vaadin" name="vaadin-theme-compiler" - rev="${vaadin.version}" conf="build" /> + <configurations> + <conf name="build" /> + <conf name="build-provided" /> + <conf name="ide" visibility="private" /> + </configurations> + <publications> + <artifact type="jar" ext="jar" /> + <artifact type="source" ext="jar" m:classifier="sources" /> + <artifact type="javadoc" ext="jar" m:classifier="javadoc" /> + <artifact type="pom" ext="pom" /> + </publications> + <dependencies> + <dependency org="com.vaadin" name="vaadin-shared" + rev="${vaadin.version}" conf="build" /> + <dependency org="com.vaadin" name="vaadin-server" + rev="${vaadin.version}" conf="build" /> + <dependency org="com.vaadin" name="vaadin-client" + rev="${vaadin.version}" conf="build" /> + <dependency org="com.vaadin" name="vaadin-theme-compiler" + rev="${vaadin.version}" conf="build" /> - <dependency org="commons-collections" name="commons-collections" - rev="3.1" conf="build,ide -> default" /> - <dependency org="commons-logging" name="commons-logging" - rev="1.1.1" conf="build,ide -> default" /> + <dependency org="commons-collections" name="commons-collections" + rev="3.1" conf="build,ide -> default" /> + <dependency org="commons-logging" name="commons-logging" + rev="1.1.1" conf="build,ide -> default" /> - <dependency org="ant" name="ant" rev="1.6.5" conf="build,ide -> default" /> - <dependency org="net.sourceforge.cssparser" name="cssparser" - rev="0.9.5" conf="build,ide -> default" /> - <dependency org="ant" name="ant" rev="1.6.5" conf="build,ide -> default" /> - <dependency org="ant" name="ant-launcher" rev="1.6.5" - conf="build,ide -> default" /> - <dependency org="org.mortbay.jetty" name="jetty" rev="6.1.11" - conf="build,ide -> default" /> - <dependency org="org.mortbay.jetty" name="jetty-util" rev="6.1.11" - conf="build,ide -> default" /> - <dependency org="org.jdesktop" name="swing-worker" rev="1.1" - conf="build,ide -> default" /> - <dependency org="commons-codec" name="commons-codec" rev="1.3" - conf="build,ide -> default" /> - <dependency org="commons-io" name="commons-io" rev="2.2" - conf="build,ide -> default" /> - <dependency org="commons-lang" name="commons-lang" rev="2.6" - conf="build,ide -> default" /> - <dependency org="org.apache.james" name="apache-mime4j" - rev="0.6" conf="build,ide -> default" /> + <dependency org="ant" name="ant" rev="1.6.5" + conf="build,ide -> default" /> + <dependency org="net.sourceforge.cssparser" name="cssparser" + rev="0.9.5" conf="build,ide -> default" /> + <dependency org="ant" name="ant" rev="1.6.5" + conf="build,ide -> default" /> + <dependency org="ant" name="ant-launcher" rev="1.6.5" + conf="build,ide -> default" /> + <dependency org="org.mortbay.jetty" name="jetty" rev="6.1.11" + conf="build,ide -> default" /> + <dependency org="org.mortbay.jetty" name="jetty-util" + rev="6.1.11" conf="build,ide -> default" /> + <dependency org="org.jdesktop" name="swing-worker" + rev="1.1" conf="build,ide -> default" /> + <dependency org="commons-codec" name="commons-codec" + rev="1.3" conf="build,ide -> default" /> + <dependency org="commons-io" name="commons-io" rev="2.2" + conf="build,ide -> default" /> + <dependency org="commons-lang" name="commons-lang" + rev="2.6" conf="build,ide -> default" /> + <dependency org="org.apache.james" name="apache-mime4j" + rev="0.6" conf="build,ide -> default" /> - <dependency org="com.vaadin" name="vaadin-client-compiler-deps" - rev="1.0.1" conf="build,ide -> default" /> + <dependency org="com.vaadin" name="vaadin-client-compiler-deps" + rev="1.0.2" conf="build,ide -> default" /> - </dependencies> + </dependencies> </ivy-module> diff --git a/client/build.xml b/client/build.xml index a2262eed7d..a027d00f60 100644 --- a/client/build.xml +++ b/client/build.xml @@ -1,43 +1,46 @@ <?xml version="1.0"?> -<project name="vaadin-client" basedir="." default="publish-local" xmlns:ivy="antlib:org.apache.ivy.ant"> - <description> - Compiles build helpers used when building other modules. - </description> - <include file="../common.xml" as="common" /> - <include file="../build.xml" as="vaadin" /> - <include file="../gwt-files.xml" as="gwtfiles" /> +<project name="vaadin-client" basedir="." default="publish-local" + xmlns:ivy="antlib:org.apache.ivy.ant"> + <description> + Compiles build helpers used when building other modules. + </description> + <include file="../common.xml" as="common" /> + <include file="../build.xml" as="vaadin" /> + <include file="../gwt-files.xml" as="gwtfiles" /> - <!-- global properties --> - <property name="module.name" value="vaadin-client" /> - <property name="module.symbolic" value="com.vaadin.client" /> - <property name="result.dir" value="result" /> + <!-- global properties --> + <property name="module.name" value="vaadin-client" /> + <property name="module.symbolic" value="com.vaadin.client" /> + <property name="result.dir" value="result" /> - <path id="classpath.compile.custom"> - <!-- Could possibly compile GWT files also here to verify that - a) the same dependencies are used and - b) all dependencies have been declared - --> - <fileset file="${gwt.user.jar}" /> - </path> - <path id="classpath.test.custom" /> + <path id="classpath.compile.custom"> + <!-- Could possibly compile GWT files also here to verify that a) + the same dependencies are used and b) all dependencies have been declared --> + <fileset file="${gwt.user.jar}" /> + </path> + <path id="classpath.test.custom" /> - <target name="jar"> - <property name="jar.file" location="${result.dir}/lib/${module.name}-${vaadin.version}.jar" /> - <antcall target="common.jar"> - <reference refid="client.gwt.includes" torefid="extra.jar.includes" /> - </antcall> - <jar destfile="${jar.file}" update="true"> - <manifest> - <attribute name="Vaadin-Package-Version" value="1" /> - <attribute name="Vaadin-Widgetsets" value="com.vaadin.DefaultWidgetSet" /> - </manifest> - </jar> - <!-- Hack to add validation dependency with source classifier --> - <property name="pom.xml" location="${result.dir}/lib/${module.name}-${vaadin.version}.pom" /> - <copy file="${pom.xml}" tofile="${temp.pom}"> - <filterchain> - <replacestring from=" </dependencies>" to=" <dependency> + <target name="jar"> + <property name="jar.file" + location="${result.dir}/lib/${module.name}-${vaadin.version}.jar" /> + <antcall target="common.jar"> + <reference refid="client.gwt.includes" torefid="extra.jar.includes" /> + </antcall> + <jar destfile="${jar.file}" update="true"> + <manifest> + <attribute name="Vaadin-Package-Version" + value="1" /> + <attribute name="Vaadin-Widgetsets" value="com.vaadin.DefaultWidgetSet" /> + </manifest> + </jar> + <!-- Hack to add validation dependency with source classifier --> + <property name="pom.xml" + location="${result.dir}/lib/${module.name}-${vaadin.version}.pom" /> + <copy file="${pom.xml}" tofile="${temp.pom}"> + <filterchain> + <replacestring from=" </dependencies>" + to=" <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.0.0.GA</version> @@ -45,32 +48,32 @@ <classifier>sources</classifier> </dependency> </dependencies>" /> - </filterchain> - </copy> - <move file="${temp.pom}" tofile="${pom.xml}" /> - </target> + </filterchain> + </copy> + <move file="${temp.pom}" tofile="${pom.xml}" /> + </target> - <target name="publish-local" depends="jar"> - <antcall target="common.sources.jar"> - <reference torefid="extra.jar.includes" refid="client.gwt.includes" /> - </antcall> - <antcall target="common.javadoc.jar" /> + <target name="publish-local" depends="jar"> + <antcall target="common.sources.jar"> + <reference torefid="extra.jar.includes" refid="client.gwt.includes" /> + </antcall> + <antcall target="common.javadoc.jar" /> - <antcall target="common.publish-local" /> - </target> + <antcall target="common.publish-local" /> + </target> - <target name="clean"> - <antcall target="common.clean" /> - </target> + <target name="clean"> + <antcall target="common.clean" /> + </target> - <target name="checkstyle"> - <antcall target="common.checkstyle"> - <param name="cs.src" location="src" /> - </antcall> - </target> + <target name="checkstyle"> + <antcall target="common.checkstyle"> + <param name="cs.src" location="src" /> + </antcall> + </target> - <target name="test" depends="checkstyle"> - <antcall target="common.test.run" /> - </target> + <target name="test" depends="checkstyle"> + <antcall target="common.test.run" /> + </target> </project>
\ No newline at end of file diff --git a/client/src/com/vaadin/DefaultWidgetSet.gwt.xml b/client/src/com/vaadin/DefaultWidgetSet.gwt.xml index 26ab7478e0..3aba1f6fee 100755 --- a/client/src/com/vaadin/DefaultWidgetSet.gwt.xml +++ b/client/src/com/vaadin/DefaultWidgetSet.gwt.xml @@ -1,13 +1,13 @@ <module> - <!-- This GWT module defines the Vaadin DefaultWidgetSet. This is the module - you want to extend when creating an extended widget set, or when creating - a specialized widget set with a subset of the components. --> + <!-- This GWT module defines the Vaadin DefaultWidgetSet. This is the + module you want to extend when creating an extended widget set, or when creating + a specialized widget set with a subset of the components. --> - <!-- Hint for WidgetSetBuilder not to automatically update the file --> - <!-- WS Compiler: manually edited --> + <!-- Hint for WidgetSetBuilder not to automatically update the file --> + <!-- WS Compiler: manually edited --> - <inherits name="com.vaadin.Vaadin" /> + <inherits name="com.vaadin.Vaadin" /> - <entry-point class="com.vaadin.client.ApplicationConfiguration" /> + <entry-point class="com.vaadin.client.ApplicationConfiguration" /> </module> diff --git a/client/src/com/vaadin/Vaadin.gwt.xml b/client/src/com/vaadin/Vaadin.gwt.xml index a4eb88d9b4..776886bb1b 100644 --- a/client/src/com/vaadin/Vaadin.gwt.xml +++ b/client/src/com/vaadin/Vaadin.gwt.xml @@ -12,13 +12,14 @@ <inherits name="com.google.gwt.http.HTTP" /> <inherits name="com.google.gwt.json.JSON" /> - + <inherits name="com.google.gwt.logging.Logging" /> - <!-- Firebug handler is deprecated but for some reason still enabled by default --> + <!-- Firebug handler is deprecated but for some reason still enabled + by default --> <set-property name="gwt.logging.firebugHandler" value="DISABLED" /> <!-- Disable popup logging as we have our own popup logger --> <set-property name="gwt.logging.popupHandler" value="DISABLED" /> - + <inherits name="com.vaadin.VaadinBrowserSpecificOverrides" /> <source path="client" /> @@ -40,21 +41,26 @@ <when-type-assignable class="com.vaadin.client.metadata.ConnectorBundleLoader" /> </generate-with> - - <replace-with class="com.vaadin.client.communication.AtmospherePushConnection"> + + <replace-with + class="com.vaadin.client.communication.AtmospherePushConnection"> <when-type-is class="com.vaadin.client.communication.PushConnection" /> - </replace-with> - - <!-- Set vaadin.profiler to true to include profiling support in the module --> + </replace-with> + + <!-- Set vaadin.profiler to true to include profiling support in the + module --> <define-property name="vaadin.profiler" values="true,false" /> - <set-property name="vaadin.profiler" value="false" /> - + <set-property name="vaadin.profiler" value="false" /> + <replace-with class="com.vaadin.client.Profiler.EnabledProfiler"> <when-type-is class="com.vaadin.client.Profiler" /> <when-property-is name="vaadin.profiler" value="true" /> - </replace-with> + </replace-with> <!-- Use the new cross site linker to get a nocache.js without document.write --> <add-linker name="xsiframe" /> + <!-- Remove IE6/IE7 permutation as they are not supported --> + <set-property name="user.agent" value="ie8,ie9,gecko1_8,safari,opera" /> + </module> diff --git a/client/src/com/vaadin/VaadinBrowserSpecificOverrides.gwt.xml b/client/src/com/vaadin/VaadinBrowserSpecificOverrides.gwt.xml index ba6c171a7d..45ede928f5 100644 --- a/client/src/com/vaadin/VaadinBrowserSpecificOverrides.gwt.xml +++ b/client/src/com/vaadin/VaadinBrowserSpecificOverrides.gwt.xml @@ -1,54 +1,55 @@ <module> - <!-- This GWT module defines the browser specific overrides used by Vaadin --> - - <!-- Hint for WidgetSetBuilder not to automatically update the file --> - <!-- WS Compiler: manually edited --> - - <!-- Fall through to this rule for everything but IE --> - <replace-with - class="com.vaadin.client.ui.upload.UploadIFrameOnloadStrategy"> - <when-type-is - class="com.vaadin.client.ui.upload.UploadIFrameOnloadStrategy" /> - </replace-with> - - <replace-with - class="com.vaadin.client.ui.upload.UploadIFrameOnloadStrategyIE"> - <when-type-is - class="com.vaadin.client.ui.upload.UploadIFrameOnloadStrategy" /> - <any> - <when-property-is name="user.agent" value="ie8" /> - </any> - </replace-with> - - <!-- Fall through to this rule for everything but IE --> - <replace-with class="com.vaadin.client.ui.VDragAndDropWrapper"> - <when-type-is class="com.vaadin.client.ui.VDragAndDropWrapper" /> - </replace-with> - - <replace-with class="com.vaadin.client.ui.VDragAndDropWrapperIE"> - <when-type-is class="com.vaadin.client.ui.VDragAndDropWrapper" /> - <any> - <when-property-is name="user.agent" value="ie8" /> - </any> - </replace-with> - - <!-- Fall through to this rule for everything but IE --> - <replace-with class="com.vaadin.client.LayoutManager"> - <when-type-is class="com.vaadin.client.LayoutManager" /> - </replace-with> - - <replace-with class="com.vaadin.client.LayoutManagerIE8"> - <when-type-is class="com.vaadin.client.LayoutManager" /> - <any> - <when-property-is name="user.agent" value="ie8" /> - </any> - </replace-with> - - <replace-with class="com.vaadin.client.ui.VPopupImpl"> - <when-type-is class="com.google.gwt.user.client.ui.impl.PopupImplMozilla" /> - <when-property-is name="user.agent" value="gecko1_8"/> - </replace-with> - + <!-- This GWT module defines the browser specific overrides used by Vaadin --> + + <!-- Hint for WidgetSetBuilder not to automatically update the file --> + <!-- WS Compiler: manually edited --> + + <!-- Fall through to this rule for everything but IE --> + <replace-with + class="com.vaadin.client.ui.upload.UploadIFrameOnloadStrategy"> + <when-type-is + class="com.vaadin.client.ui.upload.UploadIFrameOnloadStrategy" /> + </replace-with> + + <replace-with + class="com.vaadin.client.ui.upload.UploadIFrameOnloadStrategyIE"> + <when-type-is + class="com.vaadin.client.ui.upload.UploadIFrameOnloadStrategy" /> + <any> + <when-property-is name="user.agent" value="ie8" /> + </any> + </replace-with> + + <!-- Fall through to this rule for everything but IE --> + <replace-with class="com.vaadin.client.ui.VDragAndDropWrapper"> + <when-type-is class="com.vaadin.client.ui.VDragAndDropWrapper" /> + </replace-with> + + <replace-with class="com.vaadin.client.ui.VDragAndDropWrapperIE"> + <when-type-is class="com.vaadin.client.ui.VDragAndDropWrapper" /> + <any> + <when-property-is name="user.agent" value="ie8" /> + </any> + </replace-with> + + <!-- Fall through to this rule for everything but IE --> + <replace-with class="com.vaadin.client.LayoutManager"> + <when-type-is class="com.vaadin.client.LayoutManager" /> + </replace-with> + + <replace-with class="com.vaadin.client.LayoutManagerIE8"> + <when-type-is class="com.vaadin.client.LayoutManager" /> + <any> + <when-property-is name="user.agent" value="ie8" /> + </any> + </replace-with> + + <replace-with class="com.vaadin.client.ui.VPopupImpl"> + <when-type-is + class="com.google.gwt.user.client.ui.impl.PopupImplMozilla" /> + <when-property-is name="user.agent" value="gecko1_8" /> + </replace-with> + <replace-with class="com.vaadin.client.ui.VPopupImpl"> <when-type-is class="com.google.gwt.user.client.ui.impl.PopupImpl" /> </replace-with> diff --git a/client/src/com/vaadin/client/ApplicationConfiguration.java b/client/src/com/vaadin/client/ApplicationConfiguration.java index adf5e1de9d..9152e5ab23 100644 --- a/client/src/com/vaadin/client/ApplicationConfiguration.java +++ b/client/src/com/vaadin/client/ApplicationConfiguration.java @@ -38,6 +38,7 @@ import com.vaadin.client.debug.internal.ErrorNotificationHandler; import com.vaadin.client.debug.internal.HierarchySection; import com.vaadin.client.debug.internal.LogSection; import com.vaadin.client.debug.internal.NetworkSection; +import com.vaadin.client.debug.internal.ProfilerSection; import com.vaadin.client.debug.internal.Section; import com.vaadin.client.debug.internal.VDebugWindow; import com.vaadin.client.metadata.BundleLoadCallback; @@ -578,6 +579,9 @@ public class ApplicationConfiguration implements EntryPoint { } window.addSection((Section) GWT.create(HierarchySection.class)); window.addSection((Section) GWT.create(NetworkSection.class)); + if (Profiler.isEnabled()) { + window.addSection((Section) GWT.create(ProfilerSection.class)); + } if (isQuietDebugMode()) { window.close(); diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index 4141f9f2dc..ac058b5536 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -95,6 +95,7 @@ import com.vaadin.shared.communication.LegacyChangeVariablesInvocation; import com.vaadin.shared.communication.MethodInvocation; import com.vaadin.shared.communication.SharedState; import com.vaadin.shared.ui.ui.UIConstants; +import com.vaadin.shared.ui.ui.UIState.PushConfigurationState; /** * This is the client side communication "engine", managing client-server @@ -221,8 +222,6 @@ public class ApplicationConnection { private Date requestStartTime; - private boolean validatingLayouts = false; - private final LayoutManager layoutManager; private final RpcManager rpcManager; @@ -466,7 +465,8 @@ public class ApplicationConnection { Element overlayContainer = VOverlay.getOverlayContainer(this); Roles.getAlertRole().setAriaLiveProperty(overlayContainer, LiveValue.ASSERTIVE); - setOverlayContainerLabel(getUIConnector().getState().overlayContainerLabel); + VOverlay.setOverlayContainerLabel(this, + getUIConnector().getState().overlayContainerLabel); Roles.getAlertRole().setAriaRelevantProperty(overlayContainer, RelevantValue.ADDITIONS); } @@ -677,11 +677,12 @@ public class ApplicationConnection { /** * Requests an analyze of layouts, to find inconsistencies. Exclusively used * for debugging during development. + * + * @deprecated as of 7.1. Replaced by {@link UIConnector#analyzeLayouts()} */ + @Deprecated public void analyzeLayouts() { - String params = getRepaintAllParameters() + "&" - + ApplicationConstants.PARAM_ANALYZE_LAYOUTS + "=1"; - makeUidlRequest("", params); + getUIConnector().analyzeLayouts(); } /** @@ -690,12 +691,12 @@ public class ApplicationConnection { * source code. * * @param serverConnector + * @deprecated as of 7.1. Replaced by + * {@link UIConnector#showServerDebugInfo(ServerConnector)} */ + @Deprecated void highlightConnector(ServerConnector serverConnector) { - String params = getRepaintAllParameters() + "&" - + ApplicationConstants.PARAM_HIGHLIGHT_CONNECTOR + "=" - + serverConnector.getConnectorId(); - makeUidlRequest("", params); + getUIConnector().showServerDebugInfo(serverConnector); } /** @@ -1350,16 +1351,6 @@ public class ApplicationConnection { handleUIDLDuration.logDuration(" * Loading widgets completed", 10); - Profiler.enter("Handling locales"); - if (json.containsKey("locales")) { - VConsole.log(" * Handling locales"); - // Store locale data - JsArray<ValueMap> valueMapArray = json - .getJSValueMapArray("locales"); - LocaleService.addLocales(valueMapArray); - } - Profiler.leave("Handling locales"); - Profiler.enter("Handling meta information"); ValueMap meta = null; if (json.containsKey("meta")) { @@ -1367,9 +1358,6 @@ public class ApplicationConnection { meta = json.getValueMap("meta"); if (meta.containsKey("repaintAll")) { prepareRepaintAll(); - if (meta.containsKey("invalidLayouts")) { - validatingLayouts = true; - } } if (meta.containsKey("timedRedirect")) { final ValueMap timedRedirect = meta @@ -1399,6 +1387,17 @@ public class ApplicationConnection { JsArrayObject<StateChangeEvent> pendingStateChangeEvents = updateConnectorState( json, createdConnectorIds); + /* + * Doing this here so that locales are available also to the + * connectors which get a state change event before the UI. + */ + Profiler.enter("Handling locales"); + VConsole.log(" * Handling locales"); + // Store locale data + LocaleService + .addLocales(getUIConnector().getState().localeServiceState.localeData); + Profiler.leave("Handling locales"); + // Update hierarchy, do not fire events ConnectorHierarchyUpdateResult connectorHierarchyUpdateResult = updateConnectorHierarchy(json); @@ -1459,17 +1458,6 @@ public class ApplicationConnection { applicationRunning = false; } - if (validatingLayouts) { - Set<ComponentConnector> zeroHeightComponents = new HashSet<ComponentConnector>(); - Set<ComponentConnector> zeroWidthComponents = new HashSet<ComponentConnector>(); - findZeroSizeComponents(zeroHeightComponents, - zeroWidthComponents, getUIConnector()); - VConsole.printLayoutProblems(meta, - ApplicationConnection.this, - zeroHeightComponents, zeroWidthComponents); - validatingLayouts = false; - - } Profiler.leave("Error handling"); } @@ -2224,28 +2212,6 @@ public class ApplicationConnection { ApplicationConfiguration.runWhenDependenciesLoaded(c); } - private void findZeroSizeComponents( - Set<ComponentConnector> zeroHeightComponents, - Set<ComponentConnector> zeroWidthComponents, - ComponentConnector connector) { - Widget widget = connector.getWidget(); - ComputedStyle computedStyle = new ComputedStyle(widget.getElement()); - if (computedStyle.getIntProperty("height") == 0) { - zeroHeightComponents.add(connector); - } - if (computedStyle.getIntProperty("width") == 0) { - zeroWidthComponents.add(connector); - } - List<ServerConnector> children = connector.getChildren(); - for (ServerConnector serverConnector : children) { - if (serverConnector instanceof ComponentConnector) { - findZeroSizeComponents(zeroHeightComponents, - zeroWidthComponents, - (ComponentConnector) serverConnector); - } - } - } - private void loadStyleDependencies(JsArrayString dependencies) { // Assuming no reason to interpret in a defined order ResourceLoadListener resourceLoadListener = new ResourceLoadListener() { @@ -3276,14 +3242,6 @@ public class ApplicationConnection { Timer forceHandleMessage = new Timer() { @Override public void run() { - if (responseHandlingLocks.isEmpty()) { - /* - * Timer fired but there's nothing to clear. This can happen - * with IE8 as Timer.cancel is not always effective (see GWT - * issue 8101). - */ - return; - } VConsole.log("WARNING: reponse handling was never resumed, forcibly removing locks..."); responseHandlingLocks.clear(); handlePendingMessages(); @@ -3402,9 +3360,17 @@ public class ApplicationConnection { * <code>false</code> to disable the push connection. */ public void setPushEnabled(boolean enabled) { + final PushConfigurationState pushState = uIConnector.getState().pushConfiguration; + if (enabled && push == null) { push = GWT.create(PushConnection.class); - push.init(this); + push.init(this, pushState, new CommunicationErrorHandler() { + @Override + public boolean onError(String details, int statusCode) { + showCommunicationError(details, statusCode); + return true; + } + }); } else if (!enabled && push != null && push.isActive()) { push.disconnect(new Command() { @Override @@ -3415,7 +3381,7 @@ public class ApplicationConnection { * the old connection to disconnect, now is the right time * to open a new connection */ - if (uIConnector.getState().pushMode.isEnabled()) { + if (pushState.mode.isEnabled()) { setPushEnabled(true); } @@ -3434,17 +3400,4 @@ public class ApplicationConnection { public void handlePushMessage(String message) { handleJSONText(message, 200); } - - /** - * Set the label of the container element, where tooltip, notification and - * dialgs are added to. - * - * @param overlayContainerLabel - * label for the container - */ - public void setOverlayContainerLabel(String overlayContainerLabel) { - Roles.getAlertRole().setAriaLabelProperty( - VOverlay.getOverlayContainer(this), - getUIConnector().getState().overlayContainerLabel); - } } diff --git a/client/src/com/vaadin/client/DateTimeService.java b/client/src/com/vaadin/client/DateTimeService.java index 53e8f81a38..5fd0574d3e 100644 --- a/client/src/com/vaadin/client/DateTimeService.java +++ b/client/src/com/vaadin/client/DateTimeService.java @@ -308,10 +308,11 @@ public class DateTimeService { */ public String formatDate(Date date, String formatStr) { /* - * Format month names separately when locale for the DateTimeService is - * not the same as the browser locale + * Format month and day names separately when locale for the + * DateTimeService is not the same as the browser locale */ formatStr = formatMonthNames(date, formatStr); + formatStr = formatDayNames(date, formatStr); // Format uses the browser locale DateTimeFormat format = DateTimeFormat.getFormat(formatStr); @@ -321,6 +322,49 @@ public class DateTimeService { return result; } + private String formatDayNames(Date date, String formatStr) { + if (formatStr.contains("EEEE")) { + String dayName = getDay(date.getDay()); + + if (dayName != null) { + /* + * Replace 4 or more E:s with the quoted day name. Also + * concatenate generated string with any other string prepending + * or following the EEEE pattern, i.e. 'EEEE'ta ' becomes 'DAYta + * ' and not 'DAY''ta ', 'ab'EEEE becomes 'abDAY', 'x'EEEE'y' + * becomes 'xDAYy'. + */ + formatStr = formatStr.replaceAll("'([E]{4,})'", dayName); + formatStr = formatStr.replaceAll("([E]{4,})'", "'" + dayName); + formatStr = formatStr.replaceAll("'([E]{4,})", dayName + "'"); + formatStr = formatStr + .replaceAll("[E]{4,}", "'" + dayName + "'"); + } + } + + if (formatStr.contains("EEE")) { + + String dayName = getShortDay(date.getMonth()); + + if (dayName != null) { + /* + * Replace 3 or more E:s with the quoted month name. Also + * concatenate generated string with any other string prepending + * or following the EEE pattern, i.e. 'EEE'ta ' becomes 'DAYta ' + * and not 'DAY''ta ', 'ab'EEE becomes 'abDAY', 'x'EEE'y' + * becomes 'xDAYy'. + */ + formatStr = formatStr.replaceAll("'([E]{3,})'", dayName); + formatStr = formatStr.replaceAll("([E]{3,})'", "'" + dayName); + formatStr = formatStr.replaceAll("'([E]{3,})", dayName + "'"); + formatStr = formatStr + .replaceAll("[E]{3,}", "'" + dayName + "'"); + } + } + + return formatStr; + } + private String formatMonthNames(Date date, String formatStr) { if (formatStr.contains("MMMM")) { String monthName = getMonth(date.getMonth()); diff --git a/client/src/com/vaadin/client/LocaleService.java b/client/src/com/vaadin/client/LocaleService.java index 4009c95531..69345d7174 100644 --- a/client/src/com/vaadin/client/LocaleService.java +++ b/client/src/com/vaadin/client/LocaleService.java @@ -17,10 +17,12 @@ package com.vaadin.client; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; +import java.util.logging.Logger; -import com.google.gwt.core.client.JsArray; +import com.vaadin.shared.ui.ui.UIState.LocaleData; /** * Date / time etc. localisation service for all widgets. Caches all loaded @@ -31,16 +33,17 @@ import com.google.gwt.core.client.JsArray; */ public class LocaleService { - private static Map<String, ValueMap> cache = new HashMap<String, ValueMap>(); - private static String defaultLocale; + private static Map<String, LocaleData> cache = new HashMap<String, LocaleData>(); - public static void addLocale(ValueMap valueMap) { + private static String defaultLocale; - final String key = valueMap.getString("name"); + public static void addLocale(LocaleData localeData) { + final String key = localeData.name; if (cache.containsKey(key)) { cache.remove(key); } - cache.put(key, valueMap); + getLogger().fine("Received locale data for " + localeData.name); + cache.put(key, localeData); if (cache.size() == 1) { setDefaultLocale(key); } @@ -61,8 +64,7 @@ public class LocaleService { public static String[] getMonthNames(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getStringArray("mn"); + return cache.get(locale).monthNames; } else { throw new LocaleNotLoadedException(locale); } @@ -71,8 +73,7 @@ public class LocaleService { public static String[] getShortMonthNames(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getStringArray("smn"); + return cache.get(locale).shortMonthNames; } else { throw new LocaleNotLoadedException(locale); } @@ -81,8 +82,7 @@ public class LocaleService { public static String[] getDayNames(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getStringArray("dn"); + return cache.get(locale).dayNames; } else { throw new LocaleNotLoadedException(locale); } @@ -91,8 +91,7 @@ public class LocaleService { public static String[] getShortDayNames(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getStringArray("sdn"); + return cache.get(locale).shortDayNames; } else { throw new LocaleNotLoadedException(locale); } @@ -101,8 +100,7 @@ public class LocaleService { public static int getFirstDayOfWeek(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getInt("fdow"); + return cache.get(locale).firstDayOfWeek; } else { throw new LocaleNotLoadedException(locale); } @@ -111,8 +109,7 @@ public class LocaleService { public static String getDateFormat(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getString("df"); + return cache.get(locale).dateFormat; } else { throw new LocaleNotLoadedException(locale); } @@ -121,8 +118,7 @@ public class LocaleService { public static boolean isTwelveHourClock(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getBoolean("thc"); + return cache.get(locale).twelveHourClock; } else { throw new LocaleNotLoadedException(locale); } @@ -131,8 +127,7 @@ public class LocaleService { public static String getClockDelimiter(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getString("hmd"); + return cache.get(locale).hourMinuteDelimiter; } else { throw new LocaleNotLoadedException(locale); } @@ -141,20 +136,19 @@ public class LocaleService { public static String[] getAmPmStrings(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getStringArray("ampm"); + return new String[] { cache.get(locale).am, cache.get(locale).pm }; } else { throw new LocaleNotLoadedException(locale); } - } - public static void addLocales(JsArray<ValueMap> valueMapArray) { - for (int i = 0; i < valueMapArray.length(); i++) { - addLocale(valueMapArray.get(i)); - + public static void addLocales(List<LocaleData> localeDatas) { + for (LocaleData localeData : localeDatas) { + addLocale(localeData); } - } + private static Logger getLogger() { + return Logger.getLogger(LocaleService.class.getName()); + } } diff --git a/client/src/com/vaadin/client/Profiler.java b/client/src/com/vaadin/client/Profiler.java index 95b3232723..caa512b34e 100644 --- a/client/src/com/vaadin/client/Profiler.java +++ b/client/src/com/vaadin/client/Profiler.java @@ -23,13 +23,14 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.Map; +import java.util.logging.Logger; import com.google.gwt.core.client.Duration; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArray; import com.google.gwt.core.shared.GWT; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.Widget; +import com.vaadin.client.debug.internal.ProfilerSection.Node; +import com.vaadin.client.debug.internal.ProfilerSection.ProfilerResultConsumer; /** * Lightweight profiling tool that can be used to collect profiling data with @@ -96,137 +97,7 @@ public class Profiler { } } - private static class Node { - - private final String name; - private final LinkedHashMap<String, Node> children = new LinkedHashMap<String, Node>(); - private double time = 0; - private int count = 0; - - public Node(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - private Node accessChild(String name, double time) { - Node child = children.get(name); - if (child == null) { - child = new Node(name); - children.put(name, child); - } - child.time -= time; - child.count++; - return child; - } - - public double getTimeSpent() { - return time; - } - - public int getCount() { - return count; - } - - public double getOwnTime() { - double time = getTimeSpent(); - for (Node node : children.values()) { - time -= node.getTimeSpent(); - } - return time; - } - - public Widget buildTree() { - String message = getStringRepresentation(""); - - if (getName() == null || !children.isEmpty()) { - SimpleTree tree = new SimpleTree(message); - for (Node node : children.values()) { - Widget child = node.buildTree(); - tree.add(child); - } - return tree; - } else { - return new Label(message); - } - } - - public void buildRecursiveString(StringBuilder builder, String prefix) { - if (getName() != null) { - String msg = getStringRepresentation(prefix); - builder.append(msg + '\n'); - } - String childPrefix = prefix + "*"; - for (Node node : children.values()) { - node.buildRecursiveString(builder, childPrefix); - } - } - - @Override - public String toString() { - return getStringRepresentation(""); - } - - private String getStringRepresentation(String prefix) { - if (getName() == null) { - return ""; - } - String msg = prefix + " " + getName() + " in " + getTimeSpent() - + " ms."; - if (getCount() > 1) { - msg += " Invoked " - + getCount() - + " times (" - + roundToSignificantFigures(getTimeSpent() / getCount()) - + " ms per time)."; - } - if (!children.isEmpty()) { - double ownTime = getOwnTime(); - msg += " " + ownTime + " ms spent in own code"; - if (getCount() > 1) { - msg += " (" - + roundToSignificantFigures(ownTime / getCount()) - + " ms per time)"; - } - msg += '.'; - } - return msg; - } - - public static double roundToSignificantFigures(double num) { - // Number of significant digits - int n = 3; - if (num == 0) { - return 0; - } - - final double d = Math.ceil(Math.log10(num < 0 ? -num : num)); - final int power = n - (int) d; - - final double magnitude = Math.pow(10, power); - final long shifted = Math.round(num * magnitude); - return shifted / magnitude; - } - - public void sumUpTotals(Map<String, Node> totals) { - String name = getName(); - if (name != null) { - Node totalNode = totals.get(name); - if (totalNode == null) { - totalNode = new Node(name); - totals.put(name, totalNode); - } - - totalNode.time += getOwnTime(); - totalNode.count += getCount(); - } - for (Node node : children.values()) { - node.sumUpTotals(totals); - } - } - } + private static ProfilerResultConsumer consumer; /** * Checks whether the profiling gathering is enabled. @@ -323,7 +194,8 @@ public class Profiler { */ public static void logTimings() { if (!isEnabled()) { - VConsole.log("Profiler is not enabled, no data has been collected."); + getLogger().warning( + "Profiler is not enabled, no data has been collected."); return; } @@ -332,7 +204,9 @@ public class Profiler { stack.add(rootNode); JsArray<GwtStatsEvent> gwtStatsEvents = getGwtStatsEvents(); if (gwtStatsEvents.length() == 0) { - VConsole.log("No profiling events recorded, this might happen if another __gwtStatsEvent handler is installed."); + getLogger() + .warning( + "No profiling events recorded, this might happen if another __gwtStatsEvent handler is installed."); return; } @@ -347,10 +221,10 @@ public class Profiler { && !isBeginEvent; if (!inEvent && stack.size() >= 2 - && eventName.equals(stack.get(stack.size() - 2).name) + && eventName.equals(stack.get(stack.size() - 2).getName()) && !isBeginEvent) { // back out of sub event - stackTop.time += gwtStatsEvent.getMillis(); + stackTop.addTime(gwtStatsEvent.getMillis()); stack.removeLast(); stackTop = stack.getLast(); @@ -359,41 +233,35 @@ public class Profiler { if (type.equals("end")) { if (!inEvent) { - VConsole.error("Got end event for " + eventName - + " but is currently in " + stackTop.getName()); + getLogger().severe( + "Got end event for " + eventName + + " but is currently in " + + stackTop.getName()); return; } Node previousStackTop = stack.removeLast(); - previousStackTop.time += gwtStatsEvent.getMillis(); + previousStackTop.addTime(gwtStatsEvent.getMillis()); } else { if (!inEvent) { - stackTop = stackTop.accessChild(eventName, + stackTop = stackTop.enterChild(eventName, gwtStatsEvent.getMillis()); stack.add(stackTop); } if (!isBeginEvent) { // Create sub event - stack.add(stackTop.accessChild(eventName + "." + type, + stack.add(stackTop.enterChild(eventName + "." + type, gwtStatsEvent.getMillis())); } } } if (stack.size() != 1) { - VConsole.log("Not all nodes are left, the last node is " - + stack.getLast().getName()); + getLogger().warning( + "Not all nodes are left, the last node is " + + stack.getLast().getName()); return; } - StringBuilder stringBuilder = new StringBuilder(); - rootNode.buildRecursiveString(stringBuilder, ""); - - /* - * Should really output to a separate section in the debug window, but - * just dump it to the log for now. - */ - VConsole.log(stringBuilder.toString()); - Map<String, Node> totals = new HashMap<String, Node>(); rootNode.sumUpTotals(totals); @@ -405,27 +273,7 @@ public class Profiler { } }); - double total = 0; - double top20total = 0; - for (int i = 0; i < totalList.size(); i++) { - Node node = totalList.get(i); - double timeSpent = node.getTimeSpent(); - total += timeSpent; - if (i < 20) { - top20total += timeSpent; - } - } - - VConsole.log("Largest individual contributors using " + top20total - + " ms out of " + total + " ms"); - for (int i = 0; i < 20 && i < totalList.size(); i++) { - Node node = totalList.get(i); - double timeSpent = node.getTimeSpent(); - total += timeSpent; - VConsole.log(" * " + node.getName() + ": " + timeSpent + " ms in " - + node.getCount() + " invokations."); - } - + getConsumer().addProfilerData(stack.getFirst(), totalList); } /** @@ -460,28 +308,24 @@ public class Profiler { "domContentLoadedEventStart", "domContentLoadedEventEnd", "domComplete", "loadEventStart", "loadEventEnd" }; + LinkedHashMap<String, Double> timings = new LinkedHashMap<String, Double>(); + for (String key : keys) { double value = getPerformanceTiming(key); if (value == 0) { // Ignore missing value continue; } - String text = key + ": " + (now - value); - tree.add(new Label(text)); - stringBuilder.append("\n * "); - stringBuilder.append(text); + timings.put(key, Double.valueOf(now - value)); } - if (tree.getWidgetCount() == 0) { - VConsole.log("Bootstrap timings not supported, please ensure your browser supports performance.timing"); + if (timings.isEmpty()) { + getLogger() + .info("Bootstrap timings not supported, please ensure your browser supports performance.timing"); return; } - /* - * Should really output to a separate section in the debug window, - * but just dump it to the log for now. - */ - VConsole.log(stringBuilder.toString()); + getConsumer().addBootstrapData(timings); } } @@ -535,4 +379,35 @@ public class Profiler { $wnd.vaadin.gwtStatsEvents = []; }-*/; + /** + * Sets the profiler result consumer that is used to output the profiler + * data to the user. + * <p> + * <b>Warning!</b> This is internal API and should not be used by + * applications or add-ons. + * + * @since 7.1 + * @param profilerResultConsumer + * the consumer that gets profiler data + */ + public static void setProfilerResultConsuer( + ProfilerResultConsumer profilerResultConsumer) { + if (consumer != null) { + throw new IllegalStateException("The consumer has already been set"); + } + consumer = profilerResultConsumer; + } + + private static ProfilerResultConsumer getConsumer() { + if (consumer == null) { + throw new IllegalStateException("No consumer has been registered"); + } else { + return consumer; + } + } + + private static Logger getLogger() { + return Logger.getLogger(Profiler.class.getName()); + } + } diff --git a/client/src/com/vaadin/client/ResourceLoader.java b/client/src/com/vaadin/client/ResourceLoader.java index 7fc8b4f9f3..3d8eb739b1 100644 --- a/client/src/com/vaadin/client/ResourceLoader.java +++ b/client/src/com/vaadin/client/ResourceLoader.java @@ -323,7 +323,11 @@ public class ResourceLoader { } else { ObjectElement element = Document.get().createObjectElement(); element.setData(url); - element.setType("text/plain"); + if (BrowserInfo.get().isChrome()) { + element.setType("text/cache"); + } else { + element.setType("text/plain"); + } element.setHeight("0px"); element.setWidth("0px"); return element; diff --git a/client/src/com/vaadin/client/VConsole.java b/client/src/com/vaadin/client/VConsole.java index f7a7554e34..37ed8e6370 100644 --- a/client/src/com/vaadin/client/VConsole.java +++ b/client/src/com/vaadin/client/VConsole.java @@ -15,7 +15,6 @@ */ package com.vaadin.client; -import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -81,9 +80,7 @@ public class VConsole { } public static void printLayoutProblems(ValueMap meta, - ApplicationConnection applicationConnection, - Set<ComponentConnector> zeroHeightComponents, - Set<ComponentConnector> zeroWidthComponents) { + ApplicationConnection applicationConnection) { if (impl != null) { impl.meta(applicationConnection, meta); } diff --git a/client/src/com/vaadin/client/VLoadingIndicator.java b/client/src/com/vaadin/client/VLoadingIndicator.java index fcce35781d..3b6cf2252c 100644 --- a/client/src/com/vaadin/client/VLoadingIndicator.java +++ b/client/src/com/vaadin/client/VLoadingIndicator.java @@ -42,75 +42,24 @@ public class VLoadingIndicator { private int secondDelay = 1500; private int thirdDelay = 5000; - /** - * Timer with method for checking if it has been cancelled. This class is a - * workaround for a IE8 problem which causes a timer to be fired even if it - * has been cancelled. - * - * @author Vaadin Ltd - * @since 7.1 - */ - private abstract static class LoadingIndicatorTimer extends Timer { - private boolean cancelled = false; - - @Override - public void cancel() { - super.cancel(); - cancelled = true; - } - - @Override - public void schedule(int delayMillis) { - super.schedule(delayMillis); - cancelled = false; - } - - @Override - public void scheduleRepeating(int periodMillis) { - super.scheduleRepeating(periodMillis); - cancelled = false; - } - - /** - * Checks if this timer has been cancelled. - * - * @return true if the timer has been cancelled, false otherwise - */ - public boolean isCancelled() { - return cancelled; - } - } - - private Timer firstTimer = new LoadingIndicatorTimer() { + private Timer firstTimer = new Timer() { @Override public void run() { - if (isCancelled()) { - // IE8 does not properly cancel the timer in all cases. - return; - } show(); } }; - private Timer secondTimer = new LoadingIndicatorTimer() { + private Timer secondTimer = new Timer() { @Override public void run() { - if (isCancelled()) { - // IE8 does not properly cancel the timer in all cases. - return; - } getElement().setClassName(PRIMARY_STYLE_NAME); getElement().addClassName("second"); // For backwards compatibility only getElement().addClassName(PRIMARY_STYLE_NAME + "-delay"); } }; - private Timer thirdTimer = new LoadingIndicatorTimer() { + private Timer thirdTimer = new Timer() { @Override public void run() { - if (isCancelled()) { - // IE8 does not properly cancel the timer in all cases. - return; - } getElement().setClassName(PRIMARY_STYLE_NAME); getElement().addClassName("third"); // For backwards compatibility only diff --git a/client/src/com/vaadin/client/communication/AtmospherePushConnection.java b/client/src/com/vaadin/client/communication/AtmospherePushConnection.java index bc7e0b3fd2..f7936f8717 100644 --- a/client/src/com/vaadin/client/communication/AtmospherePushConnection.java +++ b/client/src/com/vaadin/client/communication/AtmospherePushConnection.java @@ -22,12 +22,15 @@ import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.Scheduler; import com.google.gwt.user.client.Command; import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.ApplicationConnection.CommunicationErrorHandler; import com.vaadin.client.ResourceLoader; import com.vaadin.client.ResourceLoader.ResourceLoadEvent; import com.vaadin.client.ResourceLoader.ResourceLoadListener; import com.vaadin.client.VConsole; import com.vaadin.shared.ApplicationConstants; +import com.vaadin.shared.communication.PushConstants; import com.vaadin.shared.ui.ui.UIConstants; +import com.vaadin.shared.ui.ui.UIState.PushConfigurationState; /** * The default {@link PushConnection} implementation that uses Atmosphere for @@ -67,8 +70,7 @@ public class AtmospherePushConnection implements PushConnection { */ protected static class FragmentedMessage { - // Jetty requires length less than buffer size - private int FRAGMENT_LENGTH = ApplicationConstants.WEBSOCKET_BUFFER_SIZE - 1; + private static final int FRAGMENT_LENGTH = PushConstants.WEBSOCKET_FRAGMENT_SIZE; private String message; private int index = 0; @@ -82,10 +84,12 @@ public class AtmospherePushConnection implements PushConnection { } public String getNextFragment() { + assert hasNextFragment(); + String result; if (index == 0) { String header = "" + message.length() - + ApplicationConstants.WEBSOCKET_MESSAGE_DELIMITER; + + PushConstants.MESSAGE_DELIMITER; int fragmentLen = FRAGMENT_LENGTH - header.length(); result = header + getFragment(0, fragmentLen); index += fragmentLen; @@ -115,6 +119,8 @@ public class AtmospherePushConnection implements PushConnection { private String transport; + private CommunicationErrorHandler errorHandler; + /** * Keeps track of the disconnect confirmation command for cases where * pending messages should be pushed before actually disconnecting. @@ -128,12 +134,21 @@ public class AtmospherePushConnection implements PushConnection { * (non-Javadoc) * * @see - * com.vaadin.client.communication.PushConenction#init(com.vaadin.client - * .ApplicationConnection) + * com.vaadin.client.communication.PushConnection#init(ApplicationConnection + * , Map<String, String>, CommunicationErrorHandler) */ @Override - public void init(final ApplicationConnection connection) { + public void init(final ApplicationConnection connection, + final PushConfigurationState pushConfiguration, + CommunicationErrorHandler errorHandler) { this.connection = connection; + this.errorHandler = errorHandler; + + config = createConfig(); + for (String param : pushConfiguration.parameters.keySet()) { + config.setStringValue(param, + pushConfiguration.parameters.get(param)); + } runWhenAtmosphereLoaded(new Command() { @Override @@ -209,9 +224,6 @@ public class AtmospherePushConnection implements PushConnection { } protected AtmosphereConfiguration getConfig() { - if (config == null) { - config = createConfig(); - } return config; } @@ -384,7 +396,8 @@ public class AtmospherePushConnection implements PushConnection { contentType: 'application/json; charset=UTF-8', reconnectInterval: '5000', maxReconnectOnClose: 10000000, - trackMessageLength: true + trackMessageLength: true, + messageDelimiter: String.fromCharCode(@com.vaadin.shared.communication.PushConstants::MESSAGE_DELIMITER) }; }-*/; @@ -430,22 +443,30 @@ public class AtmospherePushConnection implements PushConnection { if (isAtmosphereLoaded()) { command.execute(); } else { - VConsole.log("Loading " + ApplicationConstants.VAADIN_PUSH_JS); + final String pushJs = ApplicationConstants.VAADIN_PUSH_JS; + VConsole.log("Loading " + pushJs); ResourceLoader.get().loadScript( - connection.getConfiguration().getVaadinDirUrl() - + ApplicationConstants.VAADIN_PUSH_JS, + connection.getConfiguration().getVaadinDirUrl() + pushJs, new ResourceLoadListener() { @Override public void onLoad(ResourceLoadEvent event) { - VConsole.log(ApplicationConstants.VAADIN_PUSH_JS - + " loaded"); - command.execute(); + if (isAtmosphereLoaded()) { + VConsole.log(pushJs + " loaded"); + command.execute(); + } else { + // If bootstrap tried to load vaadinPush.js, + // ResourceLoader assumes it succeeded even if + // it failed (#11673) + onError(event); + } } @Override public void onError(ResourceLoadEvent event) { - VConsole.error(event.getResourceUrl() - + " could not be loaded. Push will not work."); + errorHandler.onError( + event.getResourceUrl() + + " could not be loaded. Push will not work.", + 0); } }); } diff --git a/client/src/com/vaadin/client/communication/PushConnection.java b/client/src/com/vaadin/client/communication/PushConnection.java index 61656242bd..bc2af98f1a 100644 --- a/client/src/com/vaadin/client/communication/PushConnection.java +++ b/client/src/com/vaadin/client/communication/PushConnection.java @@ -18,6 +18,8 @@ package com.vaadin.client.communication; import com.google.gwt.user.client.Command; import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.ApplicationConnection.CommunicationErrorHandler; +import com.vaadin.shared.ui.ui.UIState.PushConfigurationState; /** * Represents the client-side endpoint of a bidirectional ("push") communication @@ -37,7 +39,9 @@ public interface PushConnection { * @param connection * The ApplicationConnection */ - public void init(ApplicationConnection connection); + public void init(ApplicationConnection connection, + PushConfigurationState pushConfigurationState, + CommunicationErrorHandler errorHandler); /** * Pushes a message to the server. Will throw an exception if the connection diff --git a/client/src/com/vaadin/client/communication/StateChangeEvent.java b/client/src/com/vaadin/client/communication/StateChangeEvent.java index e17a56aa69..e8fd95e818 100644 --- a/client/src/com/vaadin/client/communication/StateChangeEvent.java +++ b/client/src/com/vaadin/client/communication/StateChangeEvent.java @@ -52,7 +52,7 @@ public class StateChangeEvent extends @Deprecated private Set<String> changedPropertiesSet; - private boolean isNewConnector = false; + private boolean initialStateChange = false; private JSONObject stateJson; @@ -110,15 +110,15 @@ public class StateChangeEvent extends * the event whose state has changed * @param stateJson * the JSON representation of the state change - * @param isNewConnector + * @param initialStateChange * <code>true</code> if the state change is for a new connector, * otherwise <code>false</code> */ public StateChangeEvent(ServerConnector connector, JSONObject stateJson, - boolean isNewConnector) { + boolean initialStateChange) { setConnector(connector); this.stateJson = stateJson; - this.isNewConnector = isNewConnector; + this.initialStateChange = initialStateChange; } @Override @@ -178,7 +178,7 @@ public class StateChangeEvent extends changedProperties = FastStringSet.create(); addJsonFields(stateJson, changedProperties, ""); - if (isNewConnector) { + if (isInitialStateChange()) { addAllStateFields( AbstractConnector.getStateType(getConnector()), changedProperties, ""); @@ -198,7 +198,7 @@ public class StateChangeEvent extends * <code>false></code> */ public boolean hasPropertyChanged(String property) { - if (isNewConnector) { + if (isInitialStateChange()) { // Everything has changed for a new connector return true; } else if (stateJson != null) { @@ -309,4 +309,17 @@ public class StateChangeEvent extends } } } + + /** + * Checks if the state change event is the first one for the given + * connector. + * + * @since 7.1 + * @return true if this is the first state change event for the connector, + * false otherwise + */ + public boolean isInitialStateChange() { + return initialStateChange; + } + } diff --git a/client/src/com/vaadin/client/debug/internal/ProfilerSection.java b/client/src/com/vaadin/client/debug/internal/ProfilerSection.java new file mode 100644 index 0000000000..f9d401de88 --- /dev/null +++ b/client/src/com/vaadin/client/debug/internal/ProfilerSection.java @@ -0,0 +1,336 @@ +package com.vaadin.client.debug.internal; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.Profiler; +import com.vaadin.client.SimpleTree; +import com.vaadin.client.ValueMap; + +/** + * Debug window section for investigating {@link Profiler} data. This section is + * only visible if the profiler is enabled ({@link Profiler#isEnabled()}). + * + * @since 7.1 + * @author Vaadin Ltd + * + * @see Profiler + */ +public class ProfilerSection implements Section { + /** + * Interface for getting data from the {@link Profiler}. + * <p> + * <b>Warning!</b> This interface is most likely to change in the future and + * is therefore defined in this class in an internal package instead of + * Profiler where it might seem more logical. + * + * @since 7.1 + * @author Vaadin Ltd + */ + public interface ProfilerResultConsumer { + public void addProfilerData(Node rootNode, List<Node> totals); + + public void addBootstrapData(LinkedHashMap<String, Double> timings); + } + + /** + * A hierarchical representation of the time spent running a named block of + * code. + * <p> + * <b>Warning!</b> This class is most likely to change in the future and is + * therefore defined in this class in an internal package instead of + * Profiler where it might seem more logical. + */ + public static class Node { + private final String name; + private final LinkedHashMap<String, Node> children = new LinkedHashMap<String, Node>(); + private double time = 0; + private int count = 0; + + /** + * Create a new node with the given name. + * + * @param name + */ + public Node(String name) { + this.name = name; + } + + /** + * Gets the name of the node + * + * @return the name of the node + */ + public String getName() { + return name; + } + + /** + * Creates a new child node or retrieves and existing child and updates + * its total time and hit count. + * + * @param name + * the name of the child + * @param time + * the timestamp for when the node is entered + * @return the child node object + */ + public Node enterChild(String name, double time) { + Node child = children.get(name); + if (child == null) { + child = new Node(name); + children.put(name, child); + } + child.time -= time; + child.count++; + return child; + } + + /** + * Gets the total time spent in this node, including time spent in sub + * nodes + * + * @return the total time spent, in milliseconds + */ + public double getTimeSpent() { + return time; + } + + /** + * Gets the number of times this node has been entered + * + * @return the number of times the node has been entered + */ + public int getCount() { + return count; + } + + /** + * Gets the total time spent in this node, excluding time spent in sub + * nodes + * + * @return the total time spent, in milliseconds + */ + public double getOwnTime() { + double time = getTimeSpent(); + for (Node node : children.values()) { + time -= node.getTimeSpent(); + } + return time; + } + + /** + * Gets the child nodes of this node + * + * @return a collection of child nodes + */ + public Collection<Node> getChildren() { + return Collections.unmodifiableCollection(children.values()); + } + + private void buildRecursiveString(StringBuilder builder, String prefix) { + if (getName() != null) { + String msg = getStringRepresentation(prefix); + builder.append(msg + '\n'); + } + String childPrefix = prefix + "*"; + for (Node node : children.values()) { + node.buildRecursiveString(builder, childPrefix); + } + } + + @Override + public String toString() { + return getStringRepresentation(""); + } + + public String getStringRepresentation(String prefix) { + if (getName() == null) { + return ""; + } + String msg = prefix + " " + getName() + " in " + getTimeSpent() + + " ms."; + if (getCount() > 1) { + msg += " Invoked " + + getCount() + + " times (" + + roundToSignificantFigures(getTimeSpent() / getCount()) + + " ms per time)."; + } + if (!children.isEmpty()) { + double ownTime = getOwnTime(); + msg += " " + ownTime + " ms spent in own code"; + if (getCount() > 1) { + msg += " (" + + roundToSignificantFigures(ownTime / getCount()) + + " ms per time)"; + } + msg += '.'; + } + return msg; + } + + private static double roundToSignificantFigures(double num) { + // Number of significant digits + int n = 3; + if (num == 0) { + return 0; + } + + final double d = Math.ceil(Math.log10(num < 0 ? -num : num)); + final int power = n - (int) d; + + final double magnitude = Math.pow(10, power); + final long shifted = Math.round(num * magnitude); + return shifted / magnitude; + } + + public void sumUpTotals(Map<String, Node> totals) { + String name = getName(); + if (name != null) { + Node totalNode = totals.get(name); + if (totalNode == null) { + totalNode = new Node(name); + totals.put(name, totalNode); + } + + totalNode.time += getOwnTime(); + totalNode.count += getCount(); + } + for (Node node : children.values()) { + node.sumUpTotals(totals); + } + } + + /** + * @since + * @param time + */ + public void addTime(double time) { + this.time += time; + } + } + + private static final int MAX_ROWS = 10; + + private final DebugButton tabButton = new DebugButton(Icon.RESET_TIMER, + "Profiler"); + + private final HorizontalPanel controls = new HorizontalPanel(); + private final FlowPanel content = new FlowPanel(); + + public ProfilerSection() { + Profiler.setProfilerResultConsuer(new ProfilerResultConsumer() { + @Override + public void addProfilerData(Node rootNode, List<Node> totals) { + double totalTime = 0; + int eventCount = 0; + for (Node node : totals) { + totalTime += node.getTimeSpent(); + eventCount += node.getCount(); + } + + SimpleTree drillDownTree = (SimpleTree) buildTree(rootNode); + drillDownTree.setText("Drill down"); + + SimpleTree offendersTree = new SimpleTree("Longest events"); + for (int i = 0; i < totals.size() && i < 20; i++) { + Node node = totals.get(i); + offendersTree.add(new Label(node + .getStringRepresentation(""))); + } + + SimpleTree root = new SimpleTree(eventCount + + " profiler events using " + totalTime + " ms"); + root.add(drillDownTree); + root.add(offendersTree); + root.open(false); + + content.add(root); + applyLimit(); + } + + @Override + public void addBootstrapData(LinkedHashMap<String, Double> timings) { + SimpleTree tree = new SimpleTree( + "Time since window.performance.timing events"); + Set<Entry<String, Double>> entrySet = timings.entrySet(); + for (Entry<String, Double> entry : entrySet) { + tree.add(new Label(entry.getValue() + " " + entry.getKey())); + } + + tree.open(false); + content.add(tree); + applyLimit(); + } + }); + } + + private Widget buildTree(Node node) { + String message = node.getStringRepresentation(""); + + Collection<Node> children = node.getChildren(); + if (node.getName() == null || !children.isEmpty()) { + SimpleTree tree = new SimpleTree(message); + for (Node childNode : children) { + Widget child = buildTree(childNode); + tree.add(child); + } + return tree; + } else { + return new Label(message); + } + } + + private void applyLimit() { + while (content.getWidgetCount() > MAX_ROWS) { + content.remove(0); + } + } + + @Override + public DebugButton getTabButton() { + return tabButton; + } + + @Override + public Widget getControls() { + return controls; + } + + @Override + public Widget getContent() { + return content; + } + + @Override + public void show() { + // Nothing to do + } + + @Override + public void hide() { + // Nothing to do + } + + @Override + public void meta(ApplicationConnection ac, ValueMap meta) { + // Nothing to do + } + + @Override + public void uidl(ApplicationConnection ac, ValueMap uidl) { + // Nothing to do + } + +} diff --git a/client/src/com/vaadin/client/debug/internal/VDebugWindow.java b/client/src/com/vaadin/client/debug/internal/VDebugWindow.java index 5aab95616a..6c05658fe1 100644 --- a/client/src/com/vaadin/client/debug/internal/VDebugWindow.java +++ b/client/src/com/vaadin/client/debug/internal/VDebugWindow.java @@ -45,6 +45,7 @@ import com.google.gwt.user.client.Window; import com.google.gwt.user.client.Window.Location; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ApplicationConnection; @@ -714,6 +715,18 @@ public final class VDebugWindow extends VOverlay { } } + /** + * Gets the container element for this window. The debug window is always + * global to the document and not related to any + * {@link ApplicationConnection} in particular. + * + * @return The global overlay container element. + */ + @Override + public com.google.gwt.user.client.Element getOverlayContainer() { + return RootPanel.get().getElement(); + } + /* * Inner classes */ diff --git a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java index 13d1e6d56c..ebc80c4728 100644 --- a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java +++ b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java @@ -51,8 +51,6 @@ public abstract class AbstractComponentConnector extends AbstractConnector private String lastKnownWidth = ""; private String lastKnownHeight = ""; - private boolean initialStateEvent = true; - private boolean tooltipListenersAttached = false; /** @@ -124,7 +122,7 @@ public abstract class AbstractComponentConnector extends AbstractConnector if (stateChangeEvent.hasPropertyChanged("id")) { if (getState().id != null) { getWidget().getElement().setId(getState().id); - } else if (!initialStateEvent) { + } else if (!stateChangeEvent.isInitialStateChange()) { getWidget().getElement().removeAttribute("id"); } } @@ -175,8 +173,6 @@ public abstract class AbstractComponentConnector extends AbstractConnector } Profiler.leave("AbstractComponentContainer.onStateChanged check tooltip"); - initialStateEvent = false; - Profiler.leave("AbstractComponentConnector.onStateChanged"); } diff --git a/client/src/com/vaadin/client/ui/VCalendar.java b/client/src/com/vaadin/client/ui/VCalendar.java index c5c12f2d72..38bcc0b14f 100644 --- a/client/src/com/vaadin/client/ui/VCalendar.java +++ b/client/src/com/vaadin/client/ui/VCalendar.java @@ -39,6 +39,8 @@ import com.vaadin.client.ui.calendar.schedule.SimpleDayToolbar; import com.vaadin.client.ui.calendar.schedule.SimpleWeekToolbar; import com.vaadin.client.ui.calendar.schedule.WeekGrid; import com.vaadin.client.ui.calendar.schedule.WeeklyLongEvents; +import com.vaadin.client.ui.calendar.schedule.dd.CalendarDropHandler; +import com.vaadin.client.ui.dd.VHasDropHandler; import com.vaadin.shared.ui.calendar.DateConstants; /** @@ -47,7 +49,7 @@ import com.vaadin.shared.ui.calendar.DateConstants; * @since 7.1 * @author Vaadin Ltd. */ -public class VCalendar extends Composite { +public class VCalendar extends Composite implements VHasDropHandler { public static final String ATTR_FIRSTDAYOFWEEK = "firstDay"; public static final String ATTR_LASTDAYOFWEEK = "lastDay"; @@ -96,6 +98,8 @@ public class VCalendar extends Composite { private int firstHour; private int lastHour; + private CalendarDropHandler dropHandler; + /** * Listener interface for listening to event click events */ @@ -1443,4 +1447,24 @@ public class VCalendar extends Composite { public void setForwardNavigationEnabled(boolean enabled) { forwardNavigationEnabled = enabled; } + + /* + * (non-Javadoc) + * + * @see com.vaadin.client.ui.dd.VHasDropHandler#getDropHandler() + */ + @Override + public CalendarDropHandler getDropHandler() { + return dropHandler; + } + + /** + * Set the drop handler + * + * @param dropHandler + * The drophandler to use + */ + public void setDropHandler(CalendarDropHandler dropHandler) { + this.dropHandler = dropHandler; + } } diff --git a/client/src/com/vaadin/client/ui/VCalendarPanel.java b/client/src/com/vaadin/client/ui/VCalendarPanel.java index 311932b819..1f40298760 100644 --- a/client/src/com/vaadin/client/ui/VCalendarPanel.java +++ b/client/src/com/vaadin/client/ui/VCalendarPanel.java @@ -2216,6 +2216,11 @@ public class VCalendarPanel extends FocusableFlexTable implements */ public void setRangeStart(Date rangeStart) { this.rangeStart = rangeStart; + if (initialRenderDone) { + // Dynamic updates to the range needs to render the calendar to + // update the element stylenames + renderCalendar(); + } } @@ -2228,6 +2233,10 @@ public class VCalendarPanel extends FocusableFlexTable implements */ public void setRangeEnd(Date rangeEnd) { this.rangeEnd = rangeEnd; - + if (initialRenderDone) { + // Dynamic updates to the range needs to render the calendar to + // update the element stylenames + renderCalendar(); + } } } diff --git a/client/src/com/vaadin/client/ui/VOverlay.java b/client/src/com/vaadin/client/ui/VOverlay.java index 9e809758ca..ced476f9dd 100644 --- a/client/src/com/vaadin/client/ui/VOverlay.java +++ b/client/src/com/vaadin/client/ui/VOverlay.java @@ -17,6 +17,7 @@ package com.vaadin.client.ui; import com.google.gwt.animation.client.Animation; +import com.google.gwt.aria.client.Roles; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.IFrameElement; import com.google.gwt.dom.client.Style; @@ -690,6 +691,23 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { return container; } + /** + * Set the label of the container element, where tooltip, notification and + * dialgs are added to. + * + * @param applicationConnection + * the application connection for which to change the label + * @param overlayContainerLabel + * label for the container + */ + public static void setOverlayContainerLabel( + ApplicationConnection applicationConnection, + String overlayContainerLabel) { + Roles.getAlertRole().setAriaLabelProperty( + VOverlay.getOverlayContainer(applicationConnection), + overlayContainerLabel); + } + @Override public void center() { super.center(); diff --git a/client/src/com/vaadin/client/ui/VPopupView.java b/client/src/com/vaadin/client/ui/VPopupView.java index 05fbd2c073..dba4c8b092 100644 --- a/client/src/com/vaadin/client/ui/VPopupView.java +++ b/client/src/com/vaadin/client/ui/VPopupView.java @@ -40,6 +40,7 @@ import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.ComponentConnector; +import com.vaadin.client.Util; import com.vaadin.client.VCaptionWrapper; import com.vaadin.client.VConsole; import com.vaadin.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner; @@ -102,6 +103,8 @@ public class VPopupView extends HTML implements Iterable<Widget> { }); popup.setAnimationEnabled(true); + + popup.setAutoHideOnHistoryEventsEnabled(false); } /** For internal use only. May be removed or replaced in the future. */ @@ -313,8 +316,11 @@ public class VPopupView extends HTML implements Iterable<Widget> { private void checkForRTE(Widget popupComponentWidget2) { if (popupComponentWidget2 instanceof VRichTextArea) { - ((VRichTextArea) popupComponentWidget2) - .synchronizeContentToServer(); + ComponentConnector rtaConnector = Util + .findConnectorFor(popupComponentWidget2); + if (rtaConnector != null) { + rtaConnector.flush(); + } } else if (popupComponentWidget2 instanceof HasWidgets) { HasWidgets hw = (HasWidgets) popupComponentWidget2; Iterator<Widget> iterator = hw.iterator(); diff --git a/client/src/com/vaadin/client/ui/VProgressBar.java b/client/src/com/vaadin/client/ui/VProgressBar.java new file mode 100644 index 0000000000..8cfc28005c --- /dev/null +++ b/client/src/com/vaadin/client/ui/VProgressBar.java @@ -0,0 +1,99 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.client.ui; + +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.ui.HasEnabled; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.client.ApplicationConnection; +import com.vaadin.shared.ui.progressindicator.ProgressBarState; + +/** + * Widget for showing the current progress of a long running task. + * <p> + * The default mode is to show the current progress internally represented by a + * floating point value between 0 and 1 (inclusive). The progress bar can also + * be in an indeterminate mode showing an animation indicating that the task is + * running but without providing any information about the current progress. + * + * @since 7.1 + * @author Vaadin Ltd + */ +public class VProgressBar extends Widget implements HasEnabled { + + Element wrapper = DOM.createDiv(); + Element indicator = DOM.createDiv(); + + private boolean indeterminate = false; + private float state = 0.0f; + private boolean enabled; + + public VProgressBar() { + setElement(DOM.createDiv()); + getElement().appendChild(wrapper); + wrapper.appendChild(indicator); + + setStylePrimaryName(ProgressBarState.PRIMARY_STYLE_NAME); + } + + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.user.client.ui.UIObject#setStylePrimaryName(java.lang. + * String) + */ + @Override + public void setStylePrimaryName(String style) { + super.setStylePrimaryName(style); + indicator.setClassName(getStylePrimaryName() + "-indicator"); + wrapper.setClassName(getStylePrimaryName() + "-wrapper"); + + } + + public void setIndeterminate(boolean indeterminate) { + this.indeterminate = indeterminate; + setStyleName(getStylePrimaryName() + "-indeterminate", indeterminate); + } + + public void setState(float state) { + final int size = Math.round(100 * state); + indicator.getStyle().setWidth(size, Unit.PCT); + } + + public boolean isIndeterminate() { + return indeterminate; + } + + public float getState() { + return state; + } + + @Override + public boolean isEnabled() { + return enabled; + } + + @Override + public void setEnabled(boolean enabled) { + this.enabled = enabled; + setStyleName(ApplicationConnection.DISABLED_CLASSNAME, !enabled); + } + +} diff --git a/client/src/com/vaadin/client/ui/VProgressIndicator.java b/client/src/com/vaadin/client/ui/VProgressIndicator.java index d6b25cb016..c75113b5f4 100644 --- a/client/src/com/vaadin/client/ui/VProgressIndicator.java +++ b/client/src/com/vaadin/client/ui/VProgressIndicator.java @@ -16,59 +16,19 @@ package com.vaadin.client.ui; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.HasEnabled; -import com.google.gwt.user.client.ui.Widget; +import com.vaadin.shared.ui.progressindicator.ProgressIndicatorState; -public class VProgressIndicator extends Widget implements HasEnabled { - - public static final String CLASSNAME = "v-progressindicator"; - Element wrapper = DOM.createDiv(); - Element indicator = DOM.createDiv(); - - protected boolean indeterminate = false; - protected float state = 0.0f; - private boolean enabled; +/** + * + * @author Vaadin Ltd + * + * @deprecated as of 7.1, renamed to VProgressBar + */ +@Deprecated +public class VProgressIndicator extends VProgressBar { public VProgressIndicator() { - setElement(DOM.createDiv()); - getElement().appendChild(wrapper); - setStyleName(CLASSNAME); - wrapper.appendChild(indicator); - indicator.setClassName(CLASSNAME + "-indicator"); - wrapper.setClassName(CLASSNAME + "-wrapper"); + super(); + setStylePrimaryName(ProgressIndicatorState.PRIMARY_STYLE_NAME); } - - public void setIndeterminate(boolean indeterminate) { - this.indeterminate = indeterminate; - setStyleName(CLASSNAME + "-indeterminate", indeterminate); - } - - public void setState(float state) { - final int size = Math.round(100 * state); - indicator.getStyle().setWidth(size, Unit.PCT); - } - - public boolean isIndeterminate() { - return indeterminate; - } - - public float getState() { - return state; - } - - @Override - public boolean isEnabled() { - return enabled; - } - - @Override - public void setEnabled(boolean enabled) { - this.enabled = enabled; - setStyleName("v-disabled", !enabled); - - } - } diff --git a/client/src/com/vaadin/client/ui/VRichTextArea.java b/client/src/com/vaadin/client/ui/VRichTextArea.java index 1498c096ed..8a6ba3fc1e 100644 --- a/client/src/com/vaadin/client/ui/VRichTextArea.java +++ b/client/src/com/vaadin/client/ui/VRichTextArea.java @@ -16,11 +16,12 @@ package com.vaadin.client.ui; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + import com.google.gwt.core.client.Scheduler; -import com.google.gwt.event.dom.client.BlurEvent; import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.ChangeEvent; -import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.KeyDownEvent; import com.google.gwt.event.dom.client.KeyDownHandler; import com.google.gwt.event.dom.client.KeyPressEvent; @@ -49,8 +50,8 @@ import com.vaadin.client.ui.richtextarea.VRichTextToolbar; * @author Vaadin Ltd. * */ -public class VRichTextArea extends Composite implements Field, ChangeHandler, - BlurHandler, KeyPressHandler, KeyDownHandler, Focusable { +public class VRichTextArea extends Composite implements Field, KeyPressHandler, + KeyDownHandler, Focusable { /** * The input node CSS classname. @@ -91,11 +92,10 @@ public class VRichTextArea extends Composite implements Field, ChangeHandler, private ShortcutActionHandlerOwner hasShortcutActionHandler; - /** For internal use only. May be removed or replaced in the future. */ - public String currentValue = ""; - private boolean readOnly = false; + private final Map<BlurHandler, HandlerRegistration> blurHandlers = new HashMap<BlurHandler, HandlerRegistration>(); + public VRichTextArea() { createRTAComponents(); fp.add(formatter); @@ -110,9 +110,19 @@ public class VRichTextArea extends Composite implements Field, ChangeHandler, private void createRTAComponents() { rta = new RichTextArea(); rta.setWidth("100%"); - rta.addBlurHandler(this); rta.addKeyDownHandler(this); formatter = new VRichTextToolbar(rta); + + // Add blur handlers + for (Entry<BlurHandler, HandlerRegistration> handler : blurHandlers + .entrySet()) { + + // Remove old registration + handler.getValue().removeHandler(); + + // Add blur handlers + addBlurHandler(handler.getKey()); + } } public void setEnabled(boolean enabled) { @@ -127,6 +137,7 @@ public class VRichTextArea extends Composite implements Field, ChangeHandler, * Swaps html to rta and visa versa. */ private void swapEditableArea() { + String value = getValue(); if (html.isAttached()) { fp.remove(html); if (BrowserInfo.get().isWebkit()) { @@ -134,13 +145,12 @@ public class VRichTextArea extends Composite implements Field, ChangeHandler, createRTAComponents(); // recreate new RTA to bypass #5379 fp.add(formatter); } - rta.setHTML(currentValue); fp.add(rta); } else { - html.setHTML(currentValue); fp.remove(rta); fp.add(html); } + setValue(value); } /** For internal use only. May be removed or replaced in the future. */ @@ -180,62 +190,6 @@ public class VRichTextArea extends Composite implements Field, ChangeHandler, return readOnly; } - // TODO is this really used, or does everything go via onBlur() only? - @Override - public void onChange(ChangeEvent event) { - synchronizeContentToServer(); - } - - /** - * Method is public to let popupview force synchronization on close. - */ - public void synchronizeContentToServer() { - if (client != null && id != null) { - final String html = sanitizeRichTextAreaValue(rta.getHTML()); - if (!html.equals(currentValue)) { - client.updateVariable(id, "text", html, immediate); - currentValue = html; - } - } - } - - /** - * Browsers differ in what they return as the content of a visually empty - * rich text area. This method is used to normalize these to an empty - * string. See #8004. - * - * @param html - * @return cleaned html string - */ - private String sanitizeRichTextAreaValue(String html) { - BrowserInfo browser = BrowserInfo.get(); - String result = html; - if (browser.isFirefox()) { - if ("<br>".equals(html)) { - result = ""; - } - } else if (browser.isWebkit()) { - if ("<div><br></div>".equals(html)) { - result = ""; - } - } else if (browser.isIE()) { - if ("<P> </P>".equals(html)) { - result = ""; - } - } else if (browser.isOpera()) { - if ("<br>".equals(html) || "<p><br></p>".equals(html)) { - result = ""; - } - } - return result; - } - - @Override - public void onBlur(BlurEvent event) { - synchronizeContentToServer(); - // TODO notify possible server side blur/focus listeners - } - /** * @return space used by components paddings and borders */ @@ -409,4 +363,81 @@ public class VRichTextArea extends Composite implements Field, ChangeHandler, rta.setTabIndex(index); } + /** + * Set the value of the text area + * + * @param value + * The text value. Can be html. + */ + public void setValue(String value) { + if (rta.isAttached()) { + rta.setHTML(value); + } else { + html.setHTML(value); + } + } + + /** + * Get the value the text area + */ + public String getValue() { + if (rta.isAttached()) { + return rta.getHTML(); + } else { + return html.getHTML(); + } + } + + /** + * Browsers differ in what they return as the content of a visually empty + * rich text area. This method is used to normalize these to an empty + * string. See #8004. + * + * @return cleaned html string + */ + public String getSanitizedValue() { + BrowserInfo browser = BrowserInfo.get(); + String result = getValue(); + if (browser.isFirefox()) { + if ("<br>".equals(html)) { + result = ""; + } + } else if (browser.isWebkit()) { + if ("<div><br></div>".equals(html)) { + result = ""; + } + } else if (browser.isIE()) { + if ("<P> </P>".equals(html)) { + result = ""; + } + } else if (browser.isOpera()) { + if ("<br>".equals(html) || "<p><br></p>".equals(html)) { + result = ""; + } + } + return result; + } + + /** + * Adds a blur handler to the component. + * + * @param blurHandler + * the blur handler to add + */ + public void addBlurHandler(BlurHandler blurHandler) { + blurHandlers.put(blurHandler, rta.addBlurHandler(blurHandler)); + } + + /** + * Removes a blur handler. + * + * @param blurHandler + * the handler to remove + */ + public void removeBlurHandler(BlurHandler blurHandler) { + HandlerRegistration registration = blurHandlers.remove(blurHandler); + if (registration != null) { + registration.removeHandler(); + } + } } diff --git a/client/src/com/vaadin/client/ui/VTabsheet.java b/client/src/com/vaadin/client/ui/VTabsheet.java index ea1cb282a6..fe29e2ebc0 100644 --- a/client/src/com/vaadin/client/ui/VTabsheet.java +++ b/client/src/com/vaadin/client/ui/VTabsheet.java @@ -860,57 +860,17 @@ public class VTabsheet extends VTabsheetBase implements Focusable, */ tab.recalculateCaptionWidth(); - UIDL tabContentUIDL = null; - ComponentConnector tabContentPaintable = null; - Widget tabContentWidget = null; - if (tabUidl.getChildCount() > 0) { - tabContentUIDL = tabUidl.getChildUIDL(0); - tabContentPaintable = client.getPaintable(tabContentUIDL); - tabContentWidget = tabContentPaintable.getWidget(); - } - - if (tabContentPaintable != null) { - /* This is a tab with content information */ - - int oldIndex = tp.getWidgetIndex(tabContentWidget); - if (oldIndex != -1 && oldIndex != index) { - /* - * The tab has previously been rendered in another position so - * we must move the cached content to correct position - */ - tp.insert(tabContentWidget, index); - } - } else { - /* A tab whose content has not yet been loaded */ - - /* - * Make sure there is a corresponding empty tab in tp. The same - * operation as the moving above but for not-loaded tabs. - */ - if (index < tp.getWidgetCount()) { - Widget oldWidget = tp.getWidget(index); - if (!(oldWidget instanceof PlaceHolder)) { - tp.insert(new PlaceHolder(), index); - } - } - - } - if (selected) { - renderContent(tabContentUIDL); + renderContent(tabUidl.getChildUIDL(0)); tb.selectTab(index); - } else { - if (tabContentUIDL != null) { - // updating a drawn child on hidden tab - if (tp.getWidgetIndex(tabContentWidget) < 0) { - tp.insert(tabContentWidget, index); - } - } else if (tp.getWidgetCount() <= index) { - tp.add(new PlaceHolder()); - } } } + /** + * @deprecated as of 7.1, VTabsheet only keeps the active tab in the DOM + * without any place holders. + */ + @Deprecated public class PlaceHolder extends VLabel { public PlaceHolder() { super(""); @@ -920,17 +880,20 @@ public class VTabsheet extends VTabsheetBase implements Focusable, private void renderContent(final UIDL contentUIDL) { final ComponentConnector content = client.getPaintable(contentUIDL); Widget newWidget = content.getWidget(); - if (tp.getWidgetCount() > activeTabIndex) { - Widget old = tp.getWidget(activeTabIndex); - if (old != newWidget) { - tp.remove(activeTabIndex); - tp.insert(content.getWidget(), activeTabIndex); - } - } else { - tp.add(content.getWidget()); + + assert tp.getWidgetCount() <= 1; + + if (tp.getWidgetCount() == 0) { + tp.add(newWidget); + } else if (tp.getWidget(0) != newWidget) { + tp.remove(0); + tp.add(newWidget); } - tp.showWidget(activeTabIndex); + assert tp.getWidgetCount() <= 1; + + // There's never any other index than 0, but maintaining API for now + tp.showWidget(0); VTabsheet.this.iLayout(); updateOpenTabSize(); @@ -1114,13 +1077,8 @@ public class VTabsheet extends VTabsheetBase implements Focusable, @Override public void removeTab(int index) { tb.removeTab(index); - /* - * This must be checked because renderTab automatically removes the - * active tab content when it changes - */ - if (tp.getWidgetCount() > index) { - tp.remove(index); - } + + // Removing content from tp is handled by the connector } @Override diff --git a/client/src/com/vaadin/client/ui/VWindow.java b/client/src/com/vaadin/client/ui/VWindow.java index 38dfdba1b8..1331eb106a 100644 --- a/client/src/com/vaadin/client/ui/VWindow.java +++ b/client/src/com/vaadin/client/ui/VWindow.java @@ -38,7 +38,6 @@ import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.BrowserInfo; @@ -793,6 +792,9 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner, int w = Util.getTouchOrMouseClientX(event) - startX + origW; int h = Util.getTouchOrMouseClientY(event) - startY + origH; + w = Math.max(w, getMinWidth()); + h = Math.max(h, getMinHeight()); + setWidth(w + "px"); setHeight(h + "px"); @@ -811,6 +813,22 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner, } } + private int getMinHeight() { + return getPixelValue(getElement().getStyle().getProperty("minHeight")); + } + + private int getMinWidth() { + return getPixelValue(getElement().getStyle().getProperty("minWidth")); + } + + private static int getPixelValue(String size) { + if (size == null || !size.endsWith("px")) { + return -1; + } else { + return Integer.parseInt(size.substring(0, size.length() - 2)); + } + } + public void updateContentsSize() { LayoutManager layoutManager = getLayoutManager(); layoutManager.setNeedsMeasure(ConnectorMap.get(client).getConnector( diff --git a/client/src/com/vaadin/client/ui/calendar/CalendarConnector.java b/client/src/com/vaadin/client/ui/calendar/CalendarConnector.java index 285d15792b..5a83579d46 100644 --- a/client/src/com/vaadin/client/ui/calendar/CalendarConnector.java +++ b/client/src/com/vaadin/client/ui/calendar/CalendarConnector.java @@ -19,6 +19,7 @@ import java.text.ParseException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import com.google.gwt.core.shared.GWT; @@ -30,6 +31,7 @@ import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.Paintable; import com.vaadin.client.TooltipInfo; import com.vaadin.client.UIDL; import com.vaadin.client.Util; @@ -57,9 +59,11 @@ import com.vaadin.client.ui.calendar.schedule.DateCell.DateCellSlot; import com.vaadin.client.ui.calendar.schedule.DateCellDayEvent; import com.vaadin.client.ui.calendar.schedule.DateUtil; import com.vaadin.client.ui.calendar.schedule.HasTooltipKey; +import com.vaadin.client.ui.calendar.schedule.MonthEventLabel; import com.vaadin.client.ui.calendar.schedule.SimpleDayCell; import com.vaadin.client.ui.calendar.schedule.dd.CalendarDropHandler; -import com.vaadin.client.ui.dd.VHasDropHandler; +import com.vaadin.client.ui.calendar.schedule.dd.CalendarMonthDropHandler; +import com.vaadin.client.ui.calendar.schedule.dd.CalendarWeekDropHandler; import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.Connect.LoadStyle; import com.vaadin.shared.ui.calendar.CalendarClientRpc; @@ -78,16 +82,16 @@ import com.vaadin.ui.Calendar; */ @Connect(value = Calendar.class, loadStyle = LoadStyle.LAZY) public class CalendarConnector extends AbstractComponentConnector implements - VHasDropHandler, ActionOwner, SimpleManagedLayout { + ActionOwner, SimpleManagedLayout, Paintable { private CalendarServerRpc rpc = RpcProxy.create(CalendarServerRpc.class, this); - private CalendarDropHandler dropHandler; - private final HashMap<String, String> actionMap = new HashMap<String, String>(); private HashMap<Object, String> tooltips = new HashMap<Object, String>(); + private static final String DROPHANDLER_ACCEPT_CRITERIA_PAINT_TAG = "-ac"; + /** * */ @@ -287,7 +291,16 @@ public class CalendarConnector extends AbstractComponentConnector implements ((VCalendarAction) action).setEvent(event); } return actions; - + } else if (widget instanceof MonthEventLabel) { + MonthEventLabel mel = (MonthEventLabel) widget; + CalendarEvent event = mel.getCalendarEvent(); + Action[] actions = CalendarConnector.this + .getActionsBetween(event.getStartTime(), + event.getEndTime()); + for (Action action : actions) { + ((VCalendarAction) action).setEvent(event); + } + return actions; } return null; } @@ -296,13 +309,16 @@ public class CalendarConnector extends AbstractComponentConnector implements }); } + private boolean showingMonthView() { + return getState().days.size() > 7; + } + @Override public void onStateChanged(StateChangeEvent stateChangeEvent) { super.onStateChanged(stateChangeEvent); CalendarState state = getState(); VCalendar widget = getWidget(); - boolean monthView = state.days.size() > 7; // Enable or disable the forward and backward navigation buttons widget.setForwardNavigationEnabled(hasEventListener(CalendarEventId.FORWARD)); @@ -326,10 +342,19 @@ public class CalendarConnector extends AbstractComponentConnector implements List<CalendarState.Day> days = state.days; List<CalendarState.Event> events = state.events; - if (monthView) { + CalendarDropHandler dropHandler = getWidget().getDropHandler(); + if (showingMonthView()) { updateMonthView(days, events); + if (dropHandler != null + && !(dropHandler instanceof CalendarMonthDropHandler)) { + getWidget().setDropHandler(new CalendarMonthDropHandler(this)); + } } else { updateWeekView(days, events); + if (dropHandler != null + && !(dropHandler instanceof CalendarWeekDropHandler)) { + getWidget().setDropHandler(new CalendarWeekDropHandler(this)); + } } updateSizes(); @@ -345,32 +370,22 @@ public class CalendarConnector extends AbstractComponentConnector implements * com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal * .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection) */ + @Override public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - // check for DD -related access criteria - // Iterator<Object> childIterator = uidl.getChildIterator(); - // while (childIterator.hasNext()) { - // UIDL child = (UIDL) childIterator.next(); - // - // // Drag&drop - // if (ACCESSCRITERIA.equals(child.getTag())) { - // if (monthView - // && !(getDropHandler() instanceof CalendarMonthDropHandler)) { - // setDropHandler(new CalendarMonthDropHandler()); - // - // } else if (!monthView - // && !(getDropHandler() instanceof CalendarWeekDropHandler)) { - // setDropHandler(new CalendarWeekDropHandler()); - // } - // - // getDropHandler().setCalendarPaintable(this); - // getDropHandler().updateAcceptRules(child); - // - // } else { - // setDropHandler(null); - // } - // - // } + Iterator<Object> childIterator = uidl.getChildIterator(); + while (childIterator.hasNext()) { + UIDL child = (UIDL) childIterator.next(); + if (DROPHANDLER_ACCEPT_CRITERIA_PAINT_TAG.equals(child.getTag())) { + if (getWidget().getDropHandler() == null) { + getWidget().setDropHandler( + showingMonthView() ? new CalendarMonthDropHandler( + this) : new CalendarWeekDropHandler(this)); + } + getWidget().getDropHandler().updateAcceptRules(child); + } else { + getWidget().setDropHandler(null); + } + } } /** @@ -439,27 +454,6 @@ public class CalendarConnector extends AbstractComponentConnector implements calendarDayListOf(days)); } - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ui.dd.VHasDropHandler#getDropHandler() - */ - @Override - public CalendarDropHandler getDropHandler() { - return dropHandler; - } - - /** - * Set the drop handler - * - * @param dropHandler - * The drophandler to use - */ - public void setDropHandler(CalendarDropHandler dropHandler) { - this.dropHandler = dropHandler; - } - private Action[] getActionsBetween(Date start, Date end) { List<Action> actions = new ArrayList<Action>(); for (int i = 0; i < actionKeys.size(); i++) { diff --git a/client/src/com/vaadin/client/ui/calendar/schedule/MonthEventLabel.java b/client/src/com/vaadin/client/ui/calendar/schedule/MonthEventLabel.java index b7f6ee7a3c..928ff85f18 100644 --- a/client/src/com/vaadin/client/ui/calendar/schedule/MonthEventLabel.java +++ b/client/src/com/vaadin/client/ui/calendar/schedule/MonthEventLabel.java @@ -17,6 +17,8 @@ package com.vaadin.client.ui.calendar.schedule; import java.util.Date; +import com.google.gwt.event.dom.client.ContextMenuEvent; +import com.google.gwt.event.dom.client.ContextMenuHandler; import com.google.gwt.user.client.ui.HTML; import com.vaadin.client.ui.VCalendar; @@ -35,11 +37,27 @@ public class MonthEventLabel extends HTML implements HasTooltipKey { private String caption; private Date time; + private CalendarEvent calendarEvent; + /** * Default constructor */ public MonthEventLabel() { setStylePrimaryName(STYLENAME); + + addDomHandler(new ContextMenuHandler() { + @Override + public void onContextMenu(ContextMenuEvent event) { + calendar.getMouseEventListener().contextMenu(event, + MonthEventLabel.this); + event.stopPropagation(); + event.preventDefault(); + } + }, ContextMenuEvent.getType()); + } + + public void setCalendarEvent(CalendarEvent e) { + calendarEvent = e; } /** @@ -139,4 +157,8 @@ public class MonthEventLabel extends HTML implements HasTooltipKey { public Object getTooltipKey() { return eventIndex; } + + public CalendarEvent getCalendarEvent() { + return calendarEvent; + } }
\ No newline at end of file diff --git a/client/src/com/vaadin/client/ui/calendar/schedule/SimpleDayCell.java b/client/src/com/vaadin/client/ui/calendar/schedule/SimpleDayCell.java index a2bd008d01..cf8006ef66 100644 --- a/client/src/com/vaadin/client/ui/calendar/schedule/SimpleDayCell.java +++ b/client/src/com/vaadin/client/ui/calendar/schedule/SimpleDayCell.java @@ -264,6 +264,7 @@ public class SimpleDayCell extends FocusableFlowPanel implements eventDiv.addMouseUpHandler(this); eventDiv.setCalendar(calendar); eventDiv.setEventIndex(e.getIndex()); + eventDiv.setCalendarEvent(e); if (timeEvent) { eventDiv.setTimeSpecificEvent(true); diff --git a/client/src/com/vaadin/client/ui/calendar/schedule/dd/CalendarDropHandler.java b/client/src/com/vaadin/client/ui/calendar/schedule/dd/CalendarDropHandler.java index aab9ca9c38..ab0c9f2e9a 100644 --- a/client/src/com/vaadin/client/ui/calendar/schedule/dd/CalendarDropHandler.java +++ b/client/src/com/vaadin/client/ui/calendar/schedule/dd/CalendarDropHandler.java @@ -28,15 +28,16 @@ import com.vaadin.client.ui.dd.VAbstractDropHandler; */ public abstract class CalendarDropHandler extends VAbstractDropHandler { - protected CalendarConnector calendarConnector; + protected final CalendarConnector calendarConnector; /** - * Set the calendar instance + * Constructor * - * @param calendarPaintable + * @param connector + * The connector of the calendar */ - public void setConnector(CalendarConnector calendarConnector) { - this.calendarConnector = calendarConnector; + public CalendarDropHandler(CalendarConnector connector) { + calendarConnector = connector; } /* diff --git a/client/src/com/vaadin/client/ui/calendar/schedule/dd/CalendarMonthDropHandler.java b/client/src/com/vaadin/client/ui/calendar/schedule/dd/CalendarMonthDropHandler.java index 913477ee14..fd0be4881e 100644 --- a/client/src/com/vaadin/client/ui/calendar/schedule/dd/CalendarMonthDropHandler.java +++ b/client/src/com/vaadin/client/ui/calendar/schedule/dd/CalendarMonthDropHandler.java @@ -18,6 +18,7 @@ package com.vaadin.client.ui.calendar.schedule.dd; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.vaadin.client.Util; +import com.vaadin.client.ui.calendar.CalendarConnector; import com.vaadin.client.ui.calendar.schedule.SimpleDayCell; import com.vaadin.client.ui.dd.VAcceptCallback; import com.vaadin.client.ui.dd.VDragEvent; @@ -32,6 +33,10 @@ import com.vaadin.client.ui.dd.VDragEvent; */ public class CalendarMonthDropHandler extends CalendarDropHandler { + public CalendarMonthDropHandler(CalendarConnector connector) { + super(connector); + } + private Element currentTargetElement; private SimpleDayCell currentTargetDay; diff --git a/client/src/com/vaadin/client/ui/calendar/schedule/dd/CalendarWeekDropHandler.java b/client/src/com/vaadin/client/ui/calendar/schedule/dd/CalendarWeekDropHandler.java index 0ea683dc3c..cede1827a2 100644 --- a/client/src/com/vaadin/client/ui/calendar/schedule/dd/CalendarWeekDropHandler.java +++ b/client/src/com/vaadin/client/ui/calendar/schedule/dd/CalendarWeekDropHandler.java @@ -18,6 +18,7 @@ package com.vaadin.client.ui.calendar.schedule.dd; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.vaadin.client.Util; +import com.vaadin.client.ui.calendar.CalendarConnector; import com.vaadin.client.ui.calendar.schedule.DateCell; import com.vaadin.client.ui.calendar.schedule.DateCellDayEvent; import com.vaadin.client.ui.dd.VAcceptCallback; @@ -36,6 +37,10 @@ public class CalendarWeekDropHandler extends CalendarDropHandler { private com.google.gwt.user.client.Element currentTargetElement; private DateCell currentTargetDay; + public CalendarWeekDropHandler(CalendarConnector connector) { + super(connector); + } + /* * (non-Javadoc) * diff --git a/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java b/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java index 345bdc0cbb..d9eac91e2b 100644 --- a/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java +++ b/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java @@ -252,8 +252,11 @@ public class ComboBoxConnector extends AbstractFieldConnector implements getWidget().setPromptingOn(); } else { // we have focus in field, prompting can't be set on, instead - // just clear the input - getWidget().tb.setValue(""); + // just clear the input if the value has changed from something + // else to null + if (getWidget().selectedOptionKey != null) { + getWidget().tb.setValue(""); + } } getWidget().setSelectedItemIcon(null); getWidget().selectedOptionKey = null; diff --git a/client/src/com/vaadin/client/ui/progressindicator/ProgressBarConnector.java b/client/src/com/vaadin/client/ui/progressindicator/ProgressBarConnector.java new file mode 100644 index 0000000000..91f3da5323 --- /dev/null +++ b/client/src/com/vaadin/client/ui/progressindicator/ProgressBarConnector.java @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.client.ui.progressindicator; + +import com.vaadin.client.communication.StateChangeEvent; +import com.vaadin.client.ui.AbstractFieldConnector; +import com.vaadin.client.ui.VProgressBar; +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.progressindicator.ProgressBarState; +import com.vaadin.ui.ProgressBar; + +/** + * Connector for {@link VProgressBar}. + * + * @since 7.1 + * @author Vaadin Ltd + */ +@Connect(ProgressBar.class) +public class ProgressBarConnector extends AbstractFieldConnector { + + public ProgressBarConnector() { + super(); + } + + @Override + public void onStateChanged(StateChangeEvent stateChangeEvent) { + super.onStateChanged(stateChangeEvent); + getWidget().setIndeterminate(getState().indeterminate); + getWidget().setState(getState().state); + } + + @Override + public ProgressBarState getState() { + return (ProgressBarState) super.getState(); + } + + @Override + public VProgressBar getWidget() { + return (VProgressBar) super.getWidget(); + } + +}
\ No newline at end of file diff --git a/client/src/com/vaadin/client/ui/progressindicator/ProgressIndicatorConnector.java b/client/src/com/vaadin/client/ui/progressindicator/ProgressIndicatorConnector.java index ac5c3f5f6b..23b71868e0 100644 --- a/client/src/com/vaadin/client/ui/progressindicator/ProgressIndicatorConnector.java +++ b/client/src/com/vaadin/client/ui/progressindicator/ProgressIndicatorConnector.java @@ -18,15 +18,24 @@ package com.vaadin.client.ui.progressindicator; import com.google.gwt.user.client.Timer; import com.vaadin.client.communication.StateChangeEvent; -import com.vaadin.client.ui.AbstractFieldConnector; +import com.vaadin.client.ui.VProgressBar; import com.vaadin.client.ui.VProgressIndicator; import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.progressindicator.ProgressIndicatorServerRpc; import com.vaadin.shared.ui.progressindicator.ProgressIndicatorState; import com.vaadin.ui.ProgressIndicator; +/** + * Connector for {@link VProgressBar} with polling support. + * + * @since 7.0 + * @author Vaadin Ltd + * @deprecated as of 7.1, use {@link ProgressBarConnector} combined with server + * push or UI polling. + */ @Connect(ProgressIndicator.class) -public class ProgressIndicatorConnector extends AbstractFieldConnector { +@Deprecated +public class ProgressIndicatorConnector extends ProgressBarConnector { @Override public ProgressIndicatorState getState() { @@ -45,8 +54,6 @@ public class ProgressIndicatorConnector extends AbstractFieldConnector { @Override public void onStateChanged(StateChangeEvent stateChangeEvent) { super.onStateChanged(stateChangeEvent); - getWidget().setIndeterminate(getState().indeterminate); - getWidget().setState(getState().state); if (isEnabled()) { poller.scheduleRepeating(getState().pollingInterval); @@ -56,13 +63,13 @@ public class ProgressIndicatorConnector extends AbstractFieldConnector { } @Override - public void onUnregister() { - super.onUnregister(); - poller.cancel(); + public VProgressIndicator getWidget() { + return (VProgressIndicator) super.getWidget(); } @Override - public VProgressIndicator getWidget() { - return (VProgressIndicator) super.getWidget(); + public void onUnregister() { + super.onUnregister(); + poller.cancel(); } } diff --git a/client/src/com/vaadin/client/ui/richtextarea/RichTextAreaConnector.java b/client/src/com/vaadin/client/ui/richtextarea/RichTextAreaConnector.java index 36182464a3..20dfc74c69 100644 --- a/client/src/com/vaadin/client/ui/richtextarea/RichTextAreaConnector.java +++ b/client/src/com/vaadin/client/ui/richtextarea/RichTextAreaConnector.java @@ -15,6 +15,8 @@ */ package com.vaadin.client.ui.richtextarea; +import com.google.gwt.event.dom.client.BlurEvent; +import com.google.gwt.event.dom.client.BlurHandler; import com.google.gwt.user.client.Event; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.Paintable; @@ -24,33 +26,47 @@ import com.vaadin.client.ui.ShortcutActionHandler.BeforeShortcutActionListener; import com.vaadin.client.ui.VRichTextArea; import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.Connect.LoadStyle; +import com.vaadin.shared.util.SharedUtil; import com.vaadin.ui.RichTextArea; @Connect(value = RichTextArea.class, loadStyle = LoadStyle.LAZY) public class RichTextAreaConnector extends AbstractFieldConnector implements Paintable, BeforeShortcutActionListener { + /* + * Last value received from the server + */ + private String cachedValue = ""; + + @Override + protected void init() { + getWidget().addBlurHandler(new BlurHandler() { + + @Override + public void onBlur(BlurEvent event) { + flush(); + } + }); + } + @Override public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) { getWidget().client = client; getWidget().id = uidl.getId(); if (uidl.hasVariable("text")) { - getWidget().currentValue = uidl.getStringVariable("text"); - if (getWidget().rta.isAttached()) { - getWidget().rta.setHTML(getWidget().currentValue); - } else { - getWidget().html.setHTML(getWidget().currentValue); + String newValue = uidl.getStringVariable("text"); + if (!SharedUtil.equals(newValue, cachedValue)) { + getWidget().setValue(newValue); + cachedValue = newValue; } } - if (isRealUpdate(uidl)) { - getWidget().setEnabled(isEnabled()); - } if (!isRealUpdate(uidl)) { return; } + getWidget().setEnabled(isEnabled()); getWidget().setReadOnly(isReadOnly()); getWidget().immediate = getState().immediate; int newMaxLength = uidl.hasAttribute("maxLength") ? uidl @@ -85,7 +101,13 @@ public class RichTextAreaConnector extends AbstractFieldConnector implements @Override public void flush() { - getWidget().synchronizeContentToServer(); + if (getConnection() != null && getConnectorId() != null) { + final String html = getWidget().getSanitizedValue(); + if (!html.equals(cachedValue)) { + getConnection().updateVariable(getConnectorId(), "text", html, + getState().immediate); + getWidget().setValue(html); + } + } }; - } diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java index 643d687f1d..45b0a7ab9d 100644 --- a/client/src/com/vaadin/client/ui/ui/UIConnector.java +++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java @@ -50,14 +50,17 @@ import com.vaadin.client.ConnectorHierarchyChangeEvent; import com.vaadin.client.ConnectorMap; import com.vaadin.client.Focusable; import com.vaadin.client.Paintable; +import com.vaadin.client.ServerConnector; import com.vaadin.client.UIDL; import com.vaadin.client.VConsole; +import com.vaadin.client.ValueMap; import com.vaadin.client.communication.StateChangeEvent; import com.vaadin.client.communication.StateChangeEvent.StateChangeHandler; import com.vaadin.client.ui.AbstractSingleComponentContainerConnector; import com.vaadin.client.ui.ClickEventHandler; import com.vaadin.client.ui.ShortcutActionHandler; import com.vaadin.client.ui.VNotification; +import com.vaadin.client.ui.VOverlay; import com.vaadin.client.ui.VUI; import com.vaadin.client.ui.layout.MayScrollChildren; import com.vaadin.client.ui.window.WindowConnector; @@ -67,6 +70,8 @@ import com.vaadin.shared.communication.MethodInvocation; import com.vaadin.shared.ui.ComponentStateUtil; import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.Connect.LoadStyle; +import com.vaadin.shared.ui.ui.DebugWindowClientRpc; +import com.vaadin.shared.ui.ui.DebugWindowServerRpc; import com.vaadin.shared.ui.ui.PageClientRpc; import com.vaadin.shared.ui.ui.PageState; import com.vaadin.shared.ui.ui.ScrollClientRpc; @@ -133,6 +138,19 @@ public class UIConnector extends AbstractSingleComponentContainerConnector }); } }); + registerRpc(DebugWindowClientRpc.class, new DebugWindowClientRpc() { + + @Override + public void reportLayoutProblems(String json) { + VConsole.printLayoutProblems(getValueMap(json), getConnection()); + } + + private native ValueMap getValueMap(String json) + /*-{ + return JSON.parse(json); + }-*/; + }); + getWidget().addResizeHandler(new ResizeHandler() { @Override public void onResize(ResizeEvent event) { @@ -626,12 +644,13 @@ public class UIConnector extends AbstractSingleComponentContainerConnector configurePolling(); } - if (stateChangeEvent.hasPropertyChanged("pushMode")) { - getConnection().setPushEnabled(getState().pushMode.isEnabled()); + if (stateChangeEvent.hasPropertyChanged("pushConfiguration")) { + getConnection().setPushEnabled( + getState().pushConfiguration.mode.isEnabled()); } if (stateChangeEvent.hasPropertyChanged("overlayContainerLabel")) { - getConnection().setOverlayContainerLabel( + VOverlay.setOverlayContainerLabel(getConnection(), getState().overlayContainerLabel); } } @@ -645,16 +664,9 @@ public class UIConnector extends AbstractSingleComponentContainerConnector pollTimer = new Timer() { @Override public void run() { - /* - * Verify that polling has not recently been canceled. This - * is needed because Timer.cancel() does not always work - * properly in IE 8 until GWT issue 8101 has been fixed. - */ - if (pollTimer != null) { - getRpcProxy(UIServerRpc.class).poll(); - // Send changes even though poll is @Delayed - getConnection().sendPendingVariableChanges(); - } + getRpcProxy(UIServerRpc.class).poll(); + // Send changes even though poll is @Delayed + getConnection().sendPendingVariableChanges(); } }; pollTimer.scheduleRepeating(getState().pollInterval); @@ -665,4 +677,27 @@ public class UIConnector extends AbstractSingleComponentContainerConnector .getName(), "poll")); } } + + /** + * Invokes the layout analyzer on the server + * + * @since 7.1 + */ + public void analyzeLayouts() { + getRpcProxy(DebugWindowServerRpc.class).analyzeLayouts(); + } + + /** + * Sends a request to the server to print details to console that will help + * the developer to locate the corresponding server-side connector in the + * source code. + * + * @since 7.1 + * @param serverConnector + * the connector to locate + */ + public void showServerDebugInfo(ServerConnector serverConnector) { + getRpcProxy(DebugWindowServerRpc.class).showServerDebugInfo( + serverConnector); + } } diff --git a/client/src/com/vaadin/client/ui/window/WindowConnector.java b/client/src/com/vaadin/client/ui/window/WindowConnector.java index 90311e30ad..4b839384a2 100644 --- a/client/src/com/vaadin/client/ui/window/WindowConnector.java +++ b/client/src/com/vaadin/client/ui/window/WindowConnector.java @@ -207,6 +207,14 @@ public class WindowConnector extends AbstractSingleComponentContainerConnector contentStyle.setPaddingBottom(footerHeight, Unit.PX); contentStyle.setMarginBottom(-footerHeight, Unit.PX); + int minWidth = lm.getOuterWidth(window.header) + - lm.getInnerWidth(window.header); + int minHeight = footerHeight + headerHeight; + + getWidget().getElement().getStyle().setPropertyPx("minWidth", minWidth); + getWidget().getElement().getStyle() + .setPropertyPx("minHeight", minHeight); + /* * Must set absolute position if the child has relative height and * there's a chance of horizontal scrolling as some browsers will @@ -384,4 +392,13 @@ public class WindowConnector extends AbstractSingleComponentContainerConnector public void setWindowOrderAndPosition() { getWidget().setWindowOrderAndPosition(); } + + @Override + public boolean hasTooltip() { + /* + * Tooltip event handler always needed on the window widget to make sure + * tooltips are properly hidden. (#11448) + */ + return true; + } } diff --git a/common.xml b/common.xml index d673273a53..e46cefd895 100644 --- a/common.xml +++ b/common.xml @@ -1,403 +1,472 @@ <?xml version="1.0" encoding="UTF-8"?> -<project name="common" basedir="." default="" xmlns:ivy="antlib:org.apache.ivy.ant" xmlns:antcontrib="antlib:net.sf.antcontrib" xmlns:cs="antlib:com.puppycrawl.tools.checkstyle"> - - <tstamp> - <format property="build.date" pattern="yyyy-MM-dd" /> - </tstamp> - - <dirname property="vaadin.basedir" file="${ant.file.common}" /> - <property name="gwt.basedir" location="${vaadin.basedir}/../gwt" /> - <property file="${vaadin.basedir}/build.properties" /> - - <property name="modules.to.publish.to.maven" value="shared,server,client,client-compiler,client-compiled,theme-compiler,themes,push" /> - <property name="modules.to.publish.to.download" value="${modules.to.publish.to.maven},all" /> - - <ivy:settings file="${vaadin.basedir}/ivysettings.xml" /> - <ivy:settings file="${vaadin.basedir}/ivysettings.xml" id="ivysettings" /> - <ivy:resolve file="${vaadin.basedir}/ivy-taskdefs.xml" conf="taskdefs" log="quiet" /> - <ivy:cachepath pathid="taskdefs.classpath" conf="taskdefs" /> - <taskdef uri="antlib:net.sf.antcontrib" resource="net/sf/antcontrib/antlib.xml" classpathref="taskdefs.classpath" /> - <!-- ant contrib for Maven integration --> - <taskdef resource="org/apache/maven/artifact/ant/antlib.xml" uri="antlib:org.apache.maven.artifact.ant" classpathref="taskdefs.classpath" /> - - <!-- FIXME These are not available in other files --> - <antcontrib:propertyregex property="vaadin.version.major" input="${vaadin.version}" regexp="([^\.]*)\.([^\.]*)\.([^\.]*)" select="\1" /> - <antcontrib:propertyregex property="vaadin.version.minor" input="${vaadin.version}" regexp="([^\.]*)\.([^\.]*)\.([^\.]*)" select="\2" /> - <antcontrib:propertyregex property="vaadin.version.revision" input="${vaadin.version}" regexp="([^\.]*)\.([^\.]*)\.([^\.]*)" select="\3" /> - - <union id="empty.reference" /> - - <property name="filtered.webcontent.dir" location="${vaadin.basedir}/result/filteredWebContent" /> - <property name="release-notes-tickets-file" location="${vaadin.basedir}/result/release-notes-tickets.html" /> - - <target name="filter.webcontent" unless="webcontent.filtered" depends="fetch-release-notes-tickets"> - <property name="webcontent.filtered" value="true" /> - <!-- Running without build.release-notes will cause an error, which is ignored --> - <loadfile property="release-notes-tickets" srcFile="${release-notes-tickets-file}" failonerror="false" /> - - <delete dir="${filtered.webcontent.dir}" /> - <copy todir="${filtered.webcontent.dir}"> - <fileset dir="${vaadin.basedir}/WebContent"> - <include name="img/**" /> - </fileset> - </copy> - <copy todir="${filtered.webcontent.dir}"> - <fileset dir="${vaadin.basedir}/WebContent"> - <patternset> - <include name="release-notes.html" /> - <include name="license.html" /> - <include name="licenses/**" /> - <include name="css/**" /> - </patternset> - </fileset> - <filterchain> - <expandproperties /> - <replacetokens begintoken="@" endtoken="@"> - <token key="version" value="${vaadin.version}" /> - </replacetokens> - <replacetokens begintoken="@" endtoken="@"> - <token key="version-minor" value="${vaadin.version.major}.${vaadin.version.minor}" /> - </replacetokens> - <replacetokens begintoken="@" endtoken="@"> - <token key="builddate" value="${build.date}" /> - </replacetokens> - <replacetokens begintoken="@" endtoken="@"> - <token key="release-notes-tickets" value="${release-notes-tickets}" /> - </replacetokens> - </filterchain> - </copy> - </target> - - <target name="fetch-release-notes-tickets" unless="built.release-notes" if="build.release-notes"> - <mkdir dir="${vaadin.basedir}/result"/> - <subant buildpath="${vaadin.basedir}/buildhelpers" target="fetch-release-notes-tickets" antfile="build.xml" inheritall="true"> - <property name="output" location="${release-notes-tickets-file}" /> - </subant> - <property name="built.release-notes" value="1" /> - </target> - - <fileset dir="${filtered.webcontent.dir}" id="common.files.for.all.jars"> - <patternset> - <include name="release-notes.html" /> - <include name="license.html" /> - <include name="licenses/**" /> - <include name="css/**" /> - <include name="img/**" /> - </patternset> - </fileset> - - - <target name="pom.xml" description="Generates a pom.xml based on the Ivy configuration. Either for a snapshot or a release version" depends="pom.xml.release,pom.xml.snapshot"> - </target> - - <target name="pom.xml.release" if="build.release"> - <fail unless="result.dir" message="No result.dir parameter given" /> - <property name="ivy.xml" location="${result.dir}/../ivy.xml" /> - <property name="pom.xml" location="${result.dir}/lib/${module.name}-${vaadin.version}.pom" /> - <property name="conf" value="build, build-provided" /> - <property name="vaadin.maven.version" value="${vaadin.version}" /> - - <ivy:makepom templatefile="${vaadin.basedir}/pom-template.xml" ivyfile="${ivy.xml}" pomfile="${pom.xml}" conf="${conf}"> - <mapping conf="build" scope="compile" /> - <mapping conf="build-provided" scope="provided" /> - </ivy:makepom> - </target> - - <target name="pom.xml.snapshot" unless="build.release"> - <fail unless="result.dir" message="No result.dir parameter given" /> - <property name="ivy.xml" location="${result.dir}/../ivy.xml" /> - <property name="pom.xml" location="${result.dir}/lib/${module.name}-${vaadin.version}.pom" /> - <property name="temp.pom.xml" location="${pom.xml}.temp" /> - <property name="conf" value="build, build-provided" /> - <property name="vaadin.maven.version" value="${vaadin.version.major}.${vaadin.version.minor}-SNAPSHOT" /> - - <ivy:makepom templatefile="${vaadin.basedir}/pom-template.xml" ivyfile="${ivy.xml}" pomfile="${temp.pom.xml}" conf="${conf}"> - <mapping conf="build" scope="compile" /> - <mapping conf="build-provided" scope="provided" /> - </ivy:makepom> - <copy file="${temp.pom.xml}" tofile="${pom.xml}"> - <filterchain> - <replacestring from="${vaadin.version}" to="${vaadin.maven.version}" /> - </filterchain> - </copy> - <delete file="${temp.pom.xml}" /> - </target> - - - <target name="sources.jar" depends="compile, filter.webcontent"> - <fail unless="result.dir" message="No result.dir parameter given" /> - <fail unless="module.name" message="No module.name parameter given" /> - <fail unless="src" message="No src directory parameter given" /> - - <property name="sources.jar" location="${result.dir}/lib/${module.name}-${vaadin.version}-sources.jar" /> - - <jar file="${sources.jar}" compress="true"> - <fileset dir="${src}"> - <patternset> - <include name="**/*.java" /> - </patternset> - </fileset> - <fileset refid="common.files.for.all.jars" /> - <restrict> - <union refid="extra.jar.includes" /> - <name name="*.java" /> - </restrict> - </jar> - - </target> - - <target name="javadoc.jar" depends="dependencies, filter.webcontent"> - <fail unless="result.dir" message="No result.dir parameter given" /> - <fail unless="module.name" message="No module.name parameter given" /> - <property name="src" location="{$result.dir}/../src" /> - <property name="javadoc.dir" value="${result.dir}/javadoc" /> - <property name="javadoc.jar" location="${result.dir}/lib/${module.name}-${vaadin.version}-javadoc.jar" /> - - <javadoc destdir="${javadoc.dir}" author="true" version="true" use="true" windowtitle="${module.name}"> - <packageset dir="${src}" excludes="${classes.exclude}" /> - <doctitle><h1>${module.name}</h1></doctitle> - <!-- <header><![CDATA[<script type="text/javascript" src=".html-style/style.js"></script>]]></header> --> - <bottom>${javadoc.bottom}</bottom> - <link offline="true" href="http://docs.oracle.com/javase/6/docs/api/" packagelistLoc="build/javadoc/j2se-1.6.0" /> - <link offline="true" href="http://java.sun.com/j2ee/1.4/docs/api/" packagelistLoc="build/javadoc/j2ee-1.4" /> - <classpath refid="classpath.compile.dependencies" /> - </javadoc> - - <!-- Create a javadoc jar --> - <jar file="${javadoc.jar}" compress="true"> - <fileset dir="${javadoc.dir}" /> - <fileset refid="common.files.for.all.jars" /> - </jar> - - </target> - - <target name="jar" depends="compile, pom.xml, filter.webcontent"> - <fail unless="result.dir" message="No result.dir parameter given" /> - <fail unless="module.name" message="No module.name parameter given" /> - - <property name="result.jar" location="${result.dir}/lib/${module.name}-${vaadin.version}.jar" /> - <property name="classes" location="{$result.dir}/classes" /> - <property name="src" location="{$result.dir}/../src" /> - - <union id="jar.files"> - <fileset dir="${classes}" excludes="${classes.exclude}" erroronmissingdir="false" /> - <fileset dir="${src}" excludes="${jar.exclude}" erroronmissingdir="false" /> - <fileset refid="common.files.for.all.jars" /> - <union refid="extra.jar.includes" /> - </union> - - <jar destfile="${result.jar}" duplicate="fail" index="true"> - <manifest> - <attribute name="Implementation-Vendor" value="${vaadin.vendor}" /> - <attribute name="Implementation-URL" value="${vaadin.url}" /> - <attribute name="Implementation-Version" value="${vaadin.version}" /> - </manifest> - <union refid="jar.files" /> - </jar> - - <antcall target="common.make-osgi-bundle"> - <param name="jar" value="${result.jar}" /> - <param name="bundle-version" value="${vaadin.version}" /> - <param name="bundle-name" value="${module.name}" /> - <param name="bundle-symbolic" value="${module.symbolic}" /> - <param name="bundle-vendor" value="${vaadin.vendor}" /> - </antcall> - - </target> - - <!-- Add OSGi attributes to the manifest of the given jar --> - <target name="make-osgi-bundle"> - <fail unless="jar" message="No jar parameter given" /> - <fail unless="bundle-name" message="No bundle-name parameter given" /> - <fail unless="bundle-symbolic" message="No bundle-symbolic parameter given" /> - <fail unless="bundle-version" message="No bundle-version parameter given" /> - <fail unless="bundle-vendor" message="No bundle-vendor parameter given" /> - - <property name="bundle-manifestversion" value="2" /> - - <jar file="${jar}" update="true"> - <manifest> - <attribute name="Bundle-Version" value="${bundle-version}" /> - <attribute name="Bundle-ManifestVersion" value="${bundle-manifestversion}" /> - <attribute name="Bundle-Name" value="${bundle-name}" /> - <attribute name="Bundle-SymbolicName" value="${bundle-symbolic}" /> - <attribute name="Bundle-Vendor" value="${bundle-vendor}" /> - <attribute name="Bundle-RequiredExecutionEnvironment" value="JavaSE-${vaadin.java.version}" /> - </manifest> - </jar> - - <antcontrib:if> - <isset property="import-package" /> - <then> - <jar file="${result.jar}" update="true"> - <manifest> - <attribute name="Import-Package" value="${import-package}" /> - </manifest> - </jar> - </then> - </antcontrib:if> - <antcontrib:if> - <isset property="require-bundle" /> - <then> - <jar file="${result.jar}" update="true"> - <manifest> - <attribute name="Require-Bundle" value="${require-bundle}" /> - </manifest> - </jar> - </then> - </antcontrib:if> - <antcontrib:if> - <isset property="export-package" /> - <then> - <jar file="${result.jar}" update="true"> - <manifest> - <attribute name="Export-Package" value="${export-package}" /> - </manifest> - </jar> - </then> - </antcontrib:if> - - <!-- Generate the Export-Package attribute in the manifest --> - <java classname="com.vaadin.buildhelpers.GeneratePackageExports" failonerror="true" fork="yes"> - <arg value="${jar}" /> - <arg line="com/vaadin com/google ${osgi.extra.package.prefixes}" /> - <classpath refid="vaadin.buildhelpers.classpath" /> - <jvmarg value="-Dvaadin.version=${vaadin.version}" /> - </java> - </target> - - <target name="compile" description="Compiles the module" depends="dependencies, directories" if="src-exists"> - <fail unless="module.name" message="No module name given" /> - - <javac srcdir="${src}" destdir="${classes}" source="${vaadin.java.version}" target="${vaadin.java.version}" debug="true" encoding="UTF-8" includeantruntime="false"> - <classpath refid="classpath.compile.dependencies" /> - <classpath refid="classpath.compile.custom" /> - </javac> - </target> - - <target name="exec-buildhelper" depends="compile"> - <fail unless="main.class" message="No main class given in 'main.class'" /> - <fail unless="output" message="No output file given in 'output'" /> - <java classname="${main.class}" output="${output}" failonerror="true" fork="yes"> - <classpath refid="vaadin.buildhelpers.classpath" /> - <classpath refid="classpath.compile.dependencies" /> - <jvmarg value="-Dvaadin.version=${vaadin.version}" /> - </java> - </target> - - <target name="directories"> - <property name="result.dir" location="result" /> - <property name="src" location="${result.dir}/../src" /> - <property name="classes" location="${result.dir}/classes" /> - <available file="${src}" type="dir" property="src-exists" /> - <mkdir dir="${classes}" /> - </target> - - <target name="test.run" depends="test.compile"> - <fail unless="module.name" message="No module name given" /> - - <property name="result.dir" location="result" /> - <property name="classes" location="${result.dir}/classes" /> - <property name="test.src" location="${result.dir}/../tests/src" /> - <property name="test.classes" location="${result.dir}/tests/classes" /> - - - <junit printsummary="withOutAndErr" fork="yes"> - <formatter usefile="false" type="plain" /> - <jvmarg value="-ea" /> - <classpath location="${test.classes}" /> - <classpath location="${classes}" /> - <classpath refid="classpath.compile.custom" /> - <classpath refid="classpath.test.dependencies" /> - - <batchtest fork="yes"> - <fileset dir="${test.src}"> - <exclude name="**/Abstract*" /> - <exclude name="com/vaadin/tests/data/bean/*" /> - <exclude name="com/vaadin/tests/util/*" /> - <exclude name="**/VaadinClasses.java" /> - <exclude name="**/*TestRunner.java" /> - <exclude name="**/SQLTestsConstants.java" /> - </fileset> - </batchtest> - </junit> - </target> - - <target name="test.compile" description="Compiles tests" depends="compile, dependencies.test"> - <fail unless="module.name" message="No module name given" /> - <property name="result.dir" location="result" /> - <property name="base.dir" location="${result.dir}/.." /> - <property name="test.src" location="${base.dir}/tests/src" /> - <property name="test.resources" location="${base.dir}/tests/resources" /> - <property name="test.classes" location="${result.dir}/tests/classes" /> - <property name="classes" location="${result.dir}/classes" /> - - <mkdir dir="${test.classes}" /> - - <javac srcdir="${test.src}" destdir="${test.classes}" source="${vaadin.java.version}" target="${vaadin.java.version}" debug="true" encoding="UTF-8" includeantruntime="false"> - <classpath refid="classpath.test.dependencies" /> - <classpath location="${classes}" /> - <classpath refid="classpath.test.custom" /> - </javac> - - <!-- Copy resources --> - <copy todir="${test.classes}" failonerror="false"> - <fileset dir="${test.resources}" /> - </copy> - </target> - - <target name="dependencies" description="Resolves dependencies needed by this module"> - <property name='conf' value="build, build-provided" /> - <ivy:resolve resolveid="common" conf="${conf}" /> - <ivy:cachepath pathid="classpath.compile.dependencies" conf="${conf}" /> - </target> - - <target name="dependencies.test" description="Resolves dependencies needed by test"> - <ivy:resolve resolveid="common" conf="test" /> - <ivy:cachepath pathid="classpath.test.dependencies" conf="test" /> - </target> - - <target name="clean"> - <fail unless="result.dir" message="No result.dir parameter given" /> - <delete dir="${result.dir}" /> - </target> - - <target name="publish-local" description="Publishes the given module to the local repository"> - <fail unless="result.dir" message="No result.dir parameter given" /> - <property name="conf" value="*(public)" /> - - <ivy:resolve conf="${conf}" /> - <ivy:publish settingsref="ivysettings" conf="${conf}" resolver="build-temp" overwrite="true" forcedeliver="true"> - <!-- <artifacts pattern="${result.dir}/[artifact]-[revision].[ext]" />--> - <artifacts pattern="${result.dir}/lib/[artifact]-[revision](-[classifier]).[ext]" /> - - </ivy:publish> - </target> - - <target name="publish.to.local.maven"> - <property name="conf" value="*(public)" /> - - <ivy:resolve conf="${conf}" /> - <ivy:publish conf="${conf}" resolver="local-maven" overwrite="true"> - </ivy:publish> - </target> - - <!-- Checkstyle conf --> - <property name="cs.dir" location="${vaadin.basedir}/checkstyle" /> - <property name="cs.xml" location="${cs.dir}/vaadin-checkstyle.xml" /> - <property name="cs.header-file" location="${cs.dir}/header" /> - <taskdef resource="checkstyletask.properties" uri="antlib:com.puppycrawl.tools.checkstyle" classpathref="taskdefs.classpath" /> - - <target name="checkstyle"> - <fail unless="result.dir" message="No result.dir parameter given" /> - <fail unless="cs.src" message="No cs.src parameter given" /> - <property name="result.dir.full" location="${result.dir}"/> - <mkdir dir="${result.dir}" /> - <echo>##teamcity[importData type='checkstyle' path='${result.dir.full}/checkstyle-errors.xml']</echo> - <cs:checkstyle config="${cs.xml}" failOnViolation="false"> - <fileset dir="${cs.src}" includes="**/*.java" /> - <formatter type="xml" toFile="${result.dir}/checkstyle-errors.xml"/> - <property key="checkstyle.header.file" file="${cs.header-file}" /> - </cs:checkstyle> - </target> +<project name="common" basedir="." default="" + xmlns:ivy="antlib:org.apache.ivy.ant" xmlns:antcontrib="antlib:net.sf.antcontrib" + xmlns:cs="antlib:com.puppycrawl.tools.checkstyle"> + + <tstamp> + <format property="build.date" pattern="yyyy-MM-dd" /> + </tstamp> + + <dirname property="vaadin.basedir" file="${ant.file.common}" /> + <property name="gwt.basedir" location="${vaadin.basedir}/../gwt" /> + <property file="${vaadin.basedir}/build.properties" /> + + <property name="modules.to.publish.to.maven" + value="shared,server,client,client-compiler,client-compiled,theme-compiler,themes,push" /> + <property name="modules.to.publish.to.download" value="${modules.to.publish.to.maven},all" /> + + <ivy:settings file="${vaadin.basedir}/ivysettings.xml" /> + <ivy:settings file="${vaadin.basedir}/ivysettings.xml" + id="ivysettings" /> + <ivy:resolve file="${vaadin.basedir}/ivy-taskdefs.xml" + conf="taskdefs" log="quiet" /> + <ivy:cachepath pathid="taskdefs.classpath" conf="taskdefs" /> + <taskdef uri="antlib:net.sf.antcontrib" resource="net/sf/antcontrib/antlib.xml" + classpathref="taskdefs.classpath" /> + <!-- ant contrib for Maven integration --> + <taskdef resource="org/apache/maven/artifact/ant/antlib.xml" + uri="antlib:org.apache.maven.artifact.ant" classpathref="taskdefs.classpath" /> + + <!-- FIXME These are not available in other files --> + <antcontrib:propertyregex property="vaadin.version.major" + input="${vaadin.version}" regexp="([^\.]*)\.([^\.]*)\.([^\.]*)" + select="\1" /> + <antcontrib:propertyregex property="vaadin.version.minor" + input="${vaadin.version}" regexp="([^\.]*)\.([^\.]*)\.([^\.]*)" + select="\2" /> + <antcontrib:propertyregex property="vaadin.version.revision" + input="${vaadin.version}" regexp="([^\.]*)\.([^\.]*)\.([^\.]*)" + select="\3" /> + + <union id="empty.reference" /> + + <property name="filtered.webcontent.dir" + location="${vaadin.basedir}/result/filteredWebContent" /> + <property name="release-notes-tickets-file" + location="${vaadin.basedir}/result/release-notes-tickets.html" /> + + <target name="filter.webcontent" unless="webcontent.filtered" + depends="fetch-release-notes-tickets"> + <property name="webcontent.filtered" value="true" /> + <!-- Running without build.release-notes will cause an error, which + is ignored --> + <loadfile property="release-notes-tickets" srcFile="${release-notes-tickets-file}" + failonerror="false" /> + + <delete dir="${filtered.webcontent.dir}" /> + <copy todir="${filtered.webcontent.dir}"> + <fileset dir="${vaadin.basedir}/WebContent"> + <include name="img/**" /> + </fileset> + </copy> + <copy todir="${filtered.webcontent.dir}"> + <fileset dir="${vaadin.basedir}/WebContent"> + <patternset> + <include name="release-notes.html" /> + <include name="license.html" /> + <include name="licenses/**" /> + <include name="css/**" /> + </patternset> + </fileset> + <filterchain> + <expandproperties /> + <replacetokens begintoken="@" endtoken="@"> + <token key="version" value="${vaadin.version}" /> + </replacetokens> + <replacetokens begintoken="@" endtoken="@"> + <token key="version-minor" + value="${vaadin.version.major}.${vaadin.version.minor}" /> + </replacetokens> + <replacetokens begintoken="@" endtoken="@"> + <token key="builddate" value="${build.date}" /> + </replacetokens> + <replacetokens begintoken="@" endtoken="@"> + <token key="release-notes-tickets" value="${release-notes-tickets}" /> + </replacetokens> + </filterchain> + </copy> + </target> + + <target name="fetch-release-notes-tickets" unless="built.release-notes" + if="build.release-notes"> + <mkdir dir="${vaadin.basedir}/result" /> + <subant buildpath="${vaadin.basedir}/buildhelpers" + target="fetch-release-notes-tickets" antfile="build.xml" + inheritall="true"> + <property name="output" location="${release-notes-tickets-file}" /> + </subant> + <property name="built.release-notes" value="1" /> + </target> + + <fileset dir="${filtered.webcontent.dir}" id="common.files.for.all.jars"> + <patternset> + <include name="release-notes.html" /> + <include name="license.html" /> + <include name="licenses/**" /> + <include name="css/**" /> + <include name="img/**" /> + </patternset> + </fileset> + + + <target name="pom.xml" + description="Generates a pom.xml based on the Ivy configuration. Either for a snapshot or a release version" + depends="pom.xml.release,pom.xml.snapshot"> + </target> + + <target name="pom.xml.release" if="build.release"> + <fail unless="result.dir" message="No result.dir parameter given" /> + <property name="ivy.xml" location="${result.dir}/../ivy.xml" /> + <property name="pom.xml" + location="${result.dir}/lib/${module.name}-${vaadin.version}.pom" /> + <property name="conf" value="build, build-provided" /> + <property name="vaadin.maven.version" value="${vaadin.version}" /> + + <ivy:makepom templatefile="${vaadin.basedir}/pom-template.xml" + ivyfile="${ivy.xml}" pomfile="${pom.xml}" conf="${conf}"> + <mapping conf="build" scope="compile" /> + <mapping conf="build-provided" scope="provided" /> + </ivy:makepom> + </target> + + <target name="pom.xml.snapshot" unless="build.release"> + <fail unless="result.dir" message="No result.dir parameter given" /> + <property name="ivy.xml" location="${result.dir}/../ivy.xml" /> + <property name="pom.xml" + location="${result.dir}/lib/${module.name}-${vaadin.version}.pom" /> + <property name="temp.pom.xml" location="${pom.xml}.temp" /> + <property name="conf" value="build, build-provided" /> + <property name="vaadin.maven.version" + value="${vaadin.version.major}.${vaadin.version.minor}-SNAPSHOT" /> + + <ivy:makepom templatefile="${vaadin.basedir}/pom-template.xml" + ivyfile="${ivy.xml}" pomfile="${temp.pom.xml}" conf="${conf}"> + <mapping conf="build" scope="compile" /> + <mapping conf="build-provided" scope="provided" /> + </ivy:makepom> + <copy file="${temp.pom.xml}" tofile="${pom.xml}"> + <filterchain> + <replacestring from="${vaadin.version}" + to="${vaadin.maven.version}" /> + </filterchain> + </copy> + <delete file="${temp.pom.xml}" /> + </target> + + + <target name="sources.jar" depends="compile, filter.webcontent"> + <fail unless="result.dir" message="No result.dir parameter given" /> + <fail unless="module.name" message="No module.name parameter given" /> + <fail unless="src" message="No src directory parameter given" /> + + <property name="sources.jar" + location="${result.dir}/lib/${module.name}-${vaadin.version}-sources.jar" /> + + <jar file="${sources.jar}" compress="true"> + <fileset dir="${src}"> + <patternset> + <include name="**/*.java" /> + </patternset> + </fileset> + <fileset refid="common.files.for.all.jars" /> + <restrict> + <union refid="extra.jar.includes" /> + <name name="*.java" /> + </restrict> + </jar> + + </target> + + <target name="javadoc.jar" depends="dependencies, filter.webcontent"> + <fail unless="result.dir" message="No result.dir parameter given" /> + <fail unless="module.name" message="No module.name parameter given" /> + <property name="src" location="{$result.dir}/../src" /> + <property name="javadoc.dir" value="${result.dir}/javadoc" /> + <property name="javadoc.jar" + location="${result.dir}/lib/${module.name}-${vaadin.version}-javadoc.jar" /> + + <javadoc destdir="${javadoc.dir}" author="true" version="true" + use="true" windowtitle="${module.name}"> + <packageset dir="${src}" excludes="${classes.exclude}" /> + <doctitle><h1>${module.name}</h1></doctitle> + <!-- <header><![CDATA[<script type="text/javascript" src=".html-style/style.js"></script>]]></header> --> + <bottom>${javadoc.bottom}</bottom> + <link offline="true" + href="http://docs.oracle.com/javase/6/docs/api/" + packagelistLoc="build/javadoc/j2se-1.6.0" /> + <link offline="true" href="http://java.sun.com/j2ee/1.4/docs/api/" + packagelistLoc="build/javadoc/j2ee-1.4" /> + <classpath refid="classpath.compile.dependencies" /> + </javadoc> + + <!-- Create a javadoc jar --> + <jar file="${javadoc.jar}" compress="true"> + <fileset dir="${javadoc.dir}" /> + <fileset refid="common.files.for.all.jars" /> + </jar> + + </target> + + <target name="jar" depends="compile, pom.xml, filter.webcontent"> + <fail unless="result.dir" message="No result.dir parameter given" /> + <fail unless="module.name" message="No module.name parameter given" /> + + <property name="result.jar" + location="${result.dir}/lib/${module.name}-${vaadin.version}.jar" /> + <property name="classes" location="{$result.dir}/classes" /> + <property name="src" location="{$result.dir}/../src" /> + + <union id="jar.files"> + <fileset dir="${classes}" excludes="${classes.exclude}" + erroronmissingdir="false" /> + <fileset dir="${src}" excludes="${jar.exclude}" + erroronmissingdir="false" /> + <fileset refid="common.files.for.all.jars" /> + <union refid="extra.jar.includes" /> + </union> + + <jar destfile="${result.jar}" duplicate="fail" index="true"> + <manifest> + <attribute name="Implementation-Vendor" value="${vaadin.vendor}" /> + <attribute name="Implementation-URL" value="${vaadin.url}" /> + <attribute name="Implementation-Version" + value="${vaadin.version}" /> + </manifest> + <union refid="jar.files" /> + </jar> + + <antcall target="common.make-osgi-bundle"> + <param name="jar" value="${result.jar}" /> + <param name="bundle-version" value="${vaadin.version}" /> + <param name="bundle-name" value="${module.name}" /> + <param name="bundle-symbolic" value="${module.symbolic}" /> + <param name="bundle-vendor" value="${vaadin.vendor}" /> + </antcall> + + </target> + + <!-- Add OSGi attributes to the manifest of the given jar --> + <target name="make-osgi-bundle"> + <fail unless="jar" message="No jar parameter given" /> + <fail unless="bundle-name" message="No bundle-name parameter given" /> + <fail unless="bundle-symbolic" message="No bundle-symbolic parameter given" /> + <fail unless="bundle-version" message="No bundle-version parameter given" /> + <fail unless="bundle-vendor" message="No bundle-vendor parameter given" /> + + <property name="bundle-manifestversion" value="2" /> + + <jar file="${jar}" update="true"> + <manifest> + <attribute name="Bundle-Version" value="${bundle-version}" /> + <attribute name="Bundle-ManifestVersion" + value="${bundle-manifestversion}" /> + <attribute name="Bundle-Name" value="${bundle-name}" /> + <attribute name="Bundle-SymbolicName" value="${bundle-symbolic}" /> + <attribute name="Bundle-Vendor" value="${bundle-vendor}" /> + <attribute name="Bundle-RequiredExecutionEnvironment" + value="JavaSE-${vaadin.java.version}" /> + </manifest> + </jar> + + <antcontrib:if> + <isset property="import-package" /> + <then> + <jar file="${result.jar}" update="true"> + <manifest> + <attribute name="Import-Package" + value="${import-package}" /> + </manifest> + </jar> + </then> + </antcontrib:if> + <antcontrib:if> + <isset property="require-bundle" /> + <then> + <jar file="${result.jar}" update="true"> + <manifest> + <attribute name="Require-Bundle" + value="${require-bundle}" /> + </manifest> + </jar> + </then> + </antcontrib:if> + <antcontrib:if> + <isset property="export-package" /> + <then> + <jar file="${result.jar}" update="true"> + <manifest> + <attribute name="Export-Package" + value="${export-package}" /> + </manifest> + </jar> + </then> + </antcontrib:if> + + <!-- Generate the Export-Package attribute in the manifest --> + <java classname="com.vaadin.buildhelpers.GeneratePackageExports" + failonerror="true" fork="yes"> + <arg value="${jar}" /> + <arg line="com/vaadin com/google ${osgi.extra.package.prefixes}" /> + <classpath refid="vaadin.buildhelpers.classpath" /> + <jvmarg value="-Dvaadin.version=${vaadin.version}" /> + </java> + </target> + + <target name="compile" description="Compiles the module" + depends="dependencies, directories" if="src-exists"> + <fail unless="module.name" message="No module name given" /> + + <javac srcdir="${src}" destdir="${classes}" source="${vaadin.java.version}" + target="${vaadin.java.version}" debug="true" encoding="UTF-8" + includeantruntime="false"> + <classpath refid="classpath.compile.dependencies" /> + <classpath refid="classpath.compile.custom" /> + </javac> + </target> + + <target name="exec-buildhelper" depends="compile"> + <fail unless="main.class" message="No main class given in 'main.class'" /> + <fail unless="output" message="No output file given in 'output'" /> + <java classname="${main.class}" output="${output}" + failonerror="true" fork="yes"> + <classpath refid="vaadin.buildhelpers.classpath" /> + <classpath refid="classpath.compile.dependencies" /> + <jvmarg value="-Dvaadin.version=${vaadin.version}" /> + </java> + </target> + + <target name="directories"> + <property name="result.dir" location="result" /> + <property name="src" location="${result.dir}/../src" /> + <property name="classes" location="${result.dir}/classes" /> + <available file="${src}" type="dir" property="src-exists" /> + <mkdir dir="${classes}" /> + </target> + + <target name="test.run" depends="test.compile"> + <fail unless="module.name" message="No module name given" /> + + <property name="result.dir" location="result" /> + <property name="classes" location="${result.dir}/classes" /> + <property name="test.src" location="${result.dir}/../tests/src" /> + <property name="test.classes" location="${result.dir}/tests/classes" /> + + + <junit printsummary="withOutAndErr" fork="yes"> + <formatter usefile="false" type="plain" /> + <jvmarg value="-ea" /> + <classpath location="${test.classes}" /> + <classpath location="${classes}" /> + <classpath refid="classpath.compile.custom" /> + <classpath refid="classpath.test.dependencies" /> + + <batchtest fork="yes"> + <fileset dir="${test.src}"> + <exclude name="**/Abstract*" /> + <exclude name="com/vaadin/tests/data/bean/*" /> + <exclude name="com/vaadin/tests/util/*" /> + <exclude name="**/VaadinClasses.java" /> + <exclude name="**/*TestRunner.java" /> + <exclude name="**/SQLTestsConstants.java" /> + </fileset> + </batchtest> + </junit> + </target> + + <target name="test.compile" description="Compiles tests" + depends="compile, dependencies.test"> + <fail unless="module.name" message="No module name given" /> + <property name="result.dir" location="result" /> + <property name="base.dir" location="${result.dir}/.." /> + <property name="test.src" location="${base.dir}/tests/src" /> + <property name="test.resources" location="${base.dir}/tests/resources" /> + <property name="test.classes" location="${result.dir}/tests/classes" /> + <property name="classes" location="${result.dir}/classes" /> + + <mkdir dir="${test.classes}" /> + + <javac srcdir="${test.src}" destdir="${test.classes}" + source="${vaadin.java.version}" target="${vaadin.java.version}" + debug="true" encoding="UTF-8" includeantruntime="false"> + <classpath refid="classpath.test.dependencies" /> + <classpath location="${classes}" /> + <classpath refid="classpath.test.custom" /> + </javac> + + <!-- Copy resources --> + <copy todir="${test.classes}" failonerror="false"> + <fileset dir="${test.resources}" /> + </copy> + </target> + + <target name="dependencies" description="Resolves dependencies needed by this module"> + <property name='conf' value="build, build-provided" /> + <ivy:resolve resolveid="common" conf="${conf}" /> + <ivy:cachepath pathid="classpath.compile.dependencies" + conf="${conf}" /> + </target> + + <target name="dependencies.test" description="Resolves dependencies needed by test"> + <ivy:resolve resolveid="common" conf="test" /> + <ivy:cachepath pathid="classpath.test.dependencies" + conf="test" /> + </target> + + <target name="clean"> + <fail unless="result.dir" message="No result.dir parameter given" /> + <delete dir="${result.dir}" /> + </target> + + <target name="publish-local" + description="Publishes the given module to the local repository"> + <fail unless="result.dir" message="No result.dir parameter given" /> + <property name="conf" value="*(public)" /> + + <ivy:resolve conf="${conf}" /> + <ivy:publish settingsref="ivysettings" conf="${conf}" + resolver="build-temp" overwrite="true" forcedeliver="true"> + <!-- <artifacts pattern="${result.dir}/[artifact]-[revision].[ext]" + /> --> + <artifacts + pattern="${result.dir}/lib/[artifact]-[revision](-[classifier]).[ext]" /> + + </ivy:publish> + </target> + + <target name="publish.to.local.maven"> + <property name="conf" value="*(public)" /> + + <ivy:resolve conf="${conf}" /> + <ivy:publish conf="${conf}" resolver="local-maven" + overwrite="true"> + </ivy:publish> + </target> + + <!-- Checkstyle conf --> + <property name="cs.dir" location="${vaadin.basedir}/checkstyle" /> + <property name="cs.xml" location="${cs.dir}/vaadin-checkstyle.xml" /> + <property name="cs.header-file" location="${cs.dir}/header" /> + <taskdef resource="checkstyletask.properties" uri="antlib:com.puppycrawl.tools.checkstyle" + classpathref="taskdefs.classpath" /> + + <target name="checkstyle"> + <fail unless="result.dir" message="No result.dir parameter given" /> + <fail unless="cs.src" message="No cs.src parameter given" /> + <property name="result.dir.full" location="${result.dir}" /> + <mkdir dir="${result.dir}" /> + <echo>##teamcity[importData type='checkstyle' + path='${result.dir.full}/checkstyle-errors.xml']</echo> + <cs:checkstyle config="${cs.xml}" failOnViolation="false"> + <fileset dir="${cs.src}" includes="**/*.java"> + <exclude name="com/vaadin/sass/internal/parser/Parser.java" /> + <exclude + name="com/vaadin/sass/internal/parser/ParserConstants.java" /> + <exclude + name="com/vaadin/sass/internal/parser/ParserTokenManager.java" /> + </fileset> + <formatter type="xml" + toFile="${result.dir}/checkstyle-errors.xml" /> + <property key="checkstyle.header.file" file="${cs.header-file}" /> + </cs:checkstyle> + </target> </project> diff --git a/gwt-files.xml b/gwt-files.xml index cc4b4a1e96..4f9f746c99 100644 --- a/gwt-files.xml +++ b/gwt-files.xml @@ -1,189 +1,191 @@ <?xml version="1.0"?> <project name="GWT files for Vaadin" basedir="."> - <include file="common.xml" as="common" /> - - <property name="gwt.lib.dir" location="${gwt.basedir}/build/lib" /> - <property name="gwt.eclipse.basedir" location="${gwt.basedir}/eclipse" /> - - <property name="gwt.user.jar" location="${gwt.lib.dir}/gwt-user.jar" /> - <property name="gwt.dev.jar" location="${gwt.lib.dir}/gwt-dev.jar" /> - <property name="gwt.elemental.jar" location="${gwt.lib.dir}/gwt-elemental.jar" /> - <property name="gwt.codeserver.jar" location="${gwt.lib.dir}/gwt-codeserver.jar" /> - - <available file="${gwt.dev.jar}" property="gwt.dev.jar.found" /> - <available file="${gwt.user.jar}" property="gwt.user.jar.found" /> - <available file="${gwt.elemental.jar}" property="gwt.elemental.jar.found" /> - <available file="${gwt.codeserver.jar}" property="gwt.codeserver.jar.found" /> - - <property name="gwt.unpack.dir" location="${vaadin.basedir}/build/gwt" /> - - <property name="gwt.user.jar.files" location="${gwt.unpack.dir}/gwt-user.jar" /> - <property name="gwt.dev.jar.files" location="${gwt.unpack.dir}/gwt-dev.jar" /> - <property name="gwt.elemental.jar.files" location="${gwt.unpack.dir}/gwt-elemental.jar" /> - <property name="gwt.codeserver.jar.files" location="${gwt.unpack.dir}/gwt-codeserver.jar" /> - - <target name="unpack.gwt"> - <fail unless="gwt.dev.jar.found" message="Could not find gwt-dev.jar at ${gwt.dev.jar}" /> - <fail unless="gwt.user.jar.found" message="Could not find gwt-user.jar at ${gwt.user.jar}" /> - <fail unless="gwt.elemental.jar.found" message="Could not find gwt-elemental.jar at ${gwt.elemental.jar}" /> - <fail unless="gwt.codeserver.jar.found" message="Could not find gwt-codeserver.jar at ${gwt.codeserver.jar}" /> - - <delete dir="${gwt.unpack.dir}" /> - - <mkdir dir="${gwt.user.jar.files}" /> - <mkdir dir="${gwt.dev.jar.files}" /> - <mkdir dir="${gwt.elemental.jar.files}" /> - <mkdir dir="${gwt.codeserver.jar.files}" /> - - <unzip dest="${gwt.user.jar.files}" src="${gwt.user.jar}" /> - <unzip dest="${gwt.dev.jar.files}" src="${gwt.dev.jar}" /> - <unzip dest="${gwt.elemental.jar.files}" src="${gwt.elemental.jar}" /> - <unzip dest="${gwt.codeserver.jar.files}" src="${gwt.codeserver.jar}" /> - </target> - - <union id="client-compiler.gwt.includes"> - <!-- GWT development JAR contents including many external dependencies + <include file="common.xml" as="common" /> + + <property name="gwt.lib.dir" location="${gwt.basedir}/build/lib" /> + <property name="gwt.eclipse.basedir" location="${gwt.basedir}/eclipse" /> + + <property name="gwt.user.jar" location="${gwt.lib.dir}/gwt-user.jar" /> + <property name="gwt.dev.jar" location="${gwt.lib.dir}/gwt-dev.jar" /> + <property name="gwt.elemental.jar" location="${gwt.lib.dir}/gwt-elemental.jar" /> + <property name="gwt.codeserver.jar" location="${gwt.lib.dir}/gwt-codeserver.jar" /> + + <available file="${gwt.dev.jar}" property="gwt.dev.jar.found" /> + <available file="${gwt.user.jar}" property="gwt.user.jar.found" /> + <available file="${gwt.elemental.jar}" property="gwt.elemental.jar.found" /> + <available file="${gwt.codeserver.jar}" property="gwt.codeserver.jar.found" /> + + <property name="gwt.unpack.dir" location="${vaadin.basedir}/build/gwt" /> + + <property name="gwt.user.jar.files" location="${gwt.unpack.dir}/gwt-user.jar" /> + <property name="gwt.dev.jar.files" location="${gwt.unpack.dir}/gwt-dev.jar" /> + <property name="gwt.elemental.jar.files" location="${gwt.unpack.dir}/gwt-elemental.jar" /> + <property name="gwt.codeserver.jar.files" location="${gwt.unpack.dir}/gwt-codeserver.jar" /> + + <target name="unpack.gwt"> + <fail unless="gwt.dev.jar.found" message="Could not find gwt-dev.jar at ${gwt.dev.jar}" /> + <fail unless="gwt.user.jar.found" + message="Could not find gwt-user.jar at ${gwt.user.jar}" /> + <fail unless="gwt.elemental.jar.found" + message="Could not find gwt-elemental.jar at ${gwt.elemental.jar}" /> + <fail unless="gwt.codeserver.jar.found" + message="Could not find gwt-codeserver.jar at ${gwt.codeserver.jar}" /> + + <delete dir="${gwt.unpack.dir}" /> + + <mkdir dir="${gwt.user.jar.files}" /> + <mkdir dir="${gwt.dev.jar.files}" /> + <mkdir dir="${gwt.elemental.jar.files}" /> + <mkdir dir="${gwt.codeserver.jar.files}" /> + + <unzip dest="${gwt.user.jar.files}" src="${gwt.user.jar}" /> + <unzip dest="${gwt.dev.jar.files}" src="${gwt.dev.jar}" /> + <unzip dest="${gwt.elemental.jar.files}" src="${gwt.elemental.jar}" /> + <unzip dest="${gwt.codeserver.jar.files}" src="${gwt.codeserver.jar}" /> + </target> + + <union id="client-compiler.gwt.includes"> + <!-- GWT development JAR contents including many external dependencies (for now) --> - <fileset dir="${gwt.dev.jar.files}"> - <exclude name="META-INF/**" /> - <exclude name="license*" /> - <exclude name="LICENSE*" /> - - <!-- Packages in vaadin-shared-deps.jar or declared - as dependencies --> - <exclude name="com/google/gwt/thirdparty/guava/**" /> - <exclude name="javax/servlet/**" /> - <exclude name="javax/xml/**" /> - <!-- cssparser --> - <exclude name="com/steadystate/css/**" /> - <!-- Ant & AntLauncher --> - <exclude name="org/apache/tools/**" /> - <!-- Jetty & jetty-util --> - <exclude name="org/mortbay/**" /> - <!-- Swing Worker--> - <exclude name="org/jdesktop/swingworker/**" /> - <!-- Apache commons codec & io & lang & collections & logging --> - <exclude name="org/apache/commons/codec/**" /> - <exclude name="org/apache/commons/io/**" /> - <exclude name="org/apache/commons/lang/**" /> - <exclude name="org/apache/commons/collections/**" /> - <exclude name="org/apache/commons/logging/**" /> - <!-- apache mime4j --> - <exclude name="org/apache/james/mime4j/**" /> - - <!-- client-compiler-deps --> - <exclude name="com/gargoylesoftware/" /> - <exclude name="com/google/common/" /> - <exclude name="com/google/debugging/" /> - <exclude name="com/google/gwt/dev/protobuf/" /> - <exclude name="com/google/gwt/thirdparty/debugging/" /> - <exclude name="com/google/gwt/thirdparty/javascript/" /> - <exclude name="com/google/gwt/thirdparty/mozilla/" /> - <exclude name="com/ibm/" /> - <exclude name="externs.zip" /> - <exclude name="java_cup/" /> - <exclude name="javax/annotation/" /> - <exclude name="net/sourceforge/htmlunit/" /> - <exclude name="org/apache/bcel/" /> - <exclude name="org/apache/html/" /> - <exclude name="org/apache/http/" /> - <exclude name="org/apache/NOTICE" /> - <exclude name="org/apache/regexp/" /> - <exclude name="org/apache/tapestry/" /> - <exclude name="org/apache/wml/" /> - <exclude name="org/apache/xalan/" /> - <exclude name="org/apache/xerces/" /> - <exclude name="org/apache/xml/" /> - <exclude name="org/apache/xmlcommons/" /> - <exclude name="org/apache/xpath/" /> - <exclude name="org/cyberneko/" /> - <exclude name="org/eclipse/" /> - <exclude name="org/kohsuke/" /> - <exclude name="org/w3c/" /> - <exclude name="org/xml/" /> - <exclude name="rhino_ast/" /> - <exclude name="rhinoDiff.txt" /> - <exclude name="trax/" /> - <exclude name="unicode-license.txt" /> - <exclude name="org/json" /> - - <exclude name="license/NOTICE" /> - <exclude name="license/LICENSE.dom-documentation.txt" /> - <exclude name="license/LICENSE.dom-software.txt" /> - <exclude name="license/LICENSE" /> - <exclude name="license/README.dom.txt" /> - <exclude name="license/README.sax.txt" /> - - <!-- Overridden in Vaadin --> - <exclude name="com/google/gwt/dev/About.properties" /> - - </fileset> - - <!-- GWT SuperDevMode --> - <fileset dir="${gwt.codeserver.jar.files}"> - <exclude name="META-INF/**" /> - </fileset> - </union> - - <union id="client-compiled-cache.gwt.includes"> - <!-- Precompiled GWT modules (.gwtar file) --> - <fileset dir="${gwt.user.jar.files}"> - <exclude name="META-INF/**" /> - - <!-- precompiled GWT modules (.gwtar) --> - <include name="**/*.gwtar" /> - <!-- external dependencies --> - <exclude name="javax/servlet/**" /> - <exclude name="org/w3c/css/sac/**" /> - - </fileset> - </union> - - <union id="client.gwt.includes"> - <fileset dir="${gwt.user.jar.files}"> - <exclude name="META-INF/**" /> - <!-- precompiled GWT modules (.gwtar) goes into client-compiled --> - <exclude name="**/*.gwtar" /> - <!-- These go into server --> - <exclude name="com/google/gwt/*/server/**" /> - <!-- These go into shared --> - <exclude name="com/google/gwt/*/shared/**" /> - <exclude name="com/google/gwt/*/*/shared/**" /> - <exclude name="com/google/web/bindery/*/shared/**" /> - - <!-- Used by the server, in wrong package in GWT --> - <exclude name="com/google/gwt/user/client/rpc/IsSerializable.*" /> - - <!-- These are in vaadin-shared-deps --> - <exclude name="com/google/gwt/thirdparty/streamhtmlparser/**" /> - <exclude name="org/w3c/flute/**" /> - - <!-- external dependencies --> - <exclude name="javax/servlet/**" /> - <exclude name="org/w3c/css/sac/**" /> - </fileset> - <!-- GWT Elemental --> - <fileset dir="${gwt.elemental.jar.files}"> - <exclude name="META-INF/**" /> - </fileset> - </union> - - <union id="shared.gwt.includes"> - <fileset dir="${gwt.user.jar.files}"> - <!-- Shared files from user --> - <include name="com/google/gwt/*/shared/**" /> - <include name="com/google/gwt/*/*/shared/**" /> - <include name="com/google/web/bindery/*/shared/**" /> - <include name="com/google/gwt/user/client/rpc/IsSerializable.*" /> - - </fileset> - </union> - - <union id="server.gwt.includes"> - <fileset dir="${gwt.user.jar.files}"> - <!-- Server files from gwt-user --> - <include name="com/google/gwt/*/server/**" /> - </fileset> - </union> + <fileset dir="${gwt.dev.jar.files}"> + <exclude name="META-INF/**" /> + <exclude name="license*" /> + <exclude name="LICENSE*" /> + + <!-- Packages in vaadin-shared-deps.jar or declared as dependencies --> + <exclude name="com/google/gwt/thirdparty/guava/**" /> + <exclude name="javax/servlet/**" /> + <exclude name="javax/xml/**" /> + <!-- cssparser --> + <exclude name="com/steadystate/css/**" /> + <!-- Ant & AntLauncher --> + <exclude name="org/apache/tools/**" /> + <!-- Jetty & jetty-util --> + <exclude name="org/mortbay/**" /> + <!-- Swing Worker --> + <exclude name="org/jdesktop/swingworker/**" /> + <!-- Apache commons codec & io & lang & collections & logging --> + <exclude name="org/apache/commons/codec/**" /> + <exclude name="org/apache/commons/io/**" /> + <exclude name="org/apache/commons/lang/**" /> + <exclude name="org/apache/commons/collections/**" /> + <exclude name="org/apache/commons/logging/**" /> + <!-- apache mime4j --> + <exclude name="org/apache/james/mime4j/**" /> + + <!-- client-compiler-deps --> + <exclude name="com/gargoylesoftware/" /> + <exclude name="com/google/common/" /> + <exclude name="com/google/debugging/" /> + <exclude name="com/google/gwt/dev/protobuf/" /> + <exclude name="com/google/gwt/thirdparty/debugging/" /> + <exclude name="com/google/gwt/thirdparty/javascript/" /> + <exclude name="com/google/gwt/thirdparty/mozilla/" /> + <exclude name="com/ibm/" /> + <exclude name="externs.zip" /> + <exclude name="java_cup/" /> + <exclude name="javax/annotation/" /> + <exclude name="net/sourceforge/htmlunit/" /> + <exclude name="org/apache/bcel/" /> + <exclude name="org/apache/html/" /> + <exclude name="org/apache/http/" /> + <exclude name="org/apache/NOTICE" /> + <exclude name="org/apache/regexp/" /> + <exclude name="org/apache/tapestry/" /> + <exclude name="org/apache/wml/" /> + <exclude name="org/apache/xalan/" /> + <exclude name="org/apache/xerces/" /> + <exclude name="org/apache/xml/" /> + <exclude name="org/apache/xmlcommons/" /> + <exclude name="org/apache/xpath/" /> + <exclude name="org/cyberneko/" /> + <exclude name="org/eclipse/" /> + <exclude name="org/kohsuke/" /> + <exclude name="org/w3c/" /> + <exclude name="org/xml/" /> + <exclude name="rhino_ast/" /> + <exclude name="rhinoDiff.txt" /> + <exclude name="trax/" /> + <exclude name="unicode-license.txt" /> + <exclude name="org/json" /> + + <exclude name="license/NOTICE" /> + <exclude name="license/LICENSE.dom-documentation.txt" /> + <exclude name="license/LICENSE.dom-software.txt" /> + <exclude name="license/LICENSE" /> + <exclude name="license/README.dom.txt" /> + <exclude name="license/README.sax.txt" /> + + <!-- Overridden in Vaadin --> + <exclude name="com/google/gwt/dev/About.properties" /> + + </fileset> + + <!-- GWT SuperDevMode --> + <fileset dir="${gwt.codeserver.jar.files}"> + <exclude name="META-INF/**" /> + </fileset> + </union> + + <union id="client-compiled-cache.gwt.includes"> + <!-- Precompiled GWT modules (.gwtar file) --> + <fileset dir="${gwt.user.jar.files}"> + <exclude name="META-INF/**" /> + + <!-- precompiled GWT modules (.gwtar) --> + <include name="**/*.gwtar" /> + <!-- external dependencies --> + <exclude name="javax/servlet/**" /> + <exclude name="org/w3c/css/sac/**" /> + + </fileset> + </union> + + <union id="client.gwt.includes"> + <fileset dir="${gwt.user.jar.files}"> + <exclude name="META-INF/**" /> + <!-- precompiled GWT modules (.gwtar) goes into client-compiled --> + <exclude name="**/*.gwtar" /> + <!-- These go into server --> + <exclude name="com/google/gwt/*/server/**" /> + <!-- These go into shared --> + <exclude name="com/google/gwt/*/shared/**" /> + <exclude name="com/google/gwt/*/*/shared/**" /> + <exclude name="com/google/web/bindery/*/shared/**" /> + + <!-- Used by the server, in wrong package in GWT --> + <exclude name="com/google/gwt/user/client/rpc/IsSerializable.*" /> + + <!-- These are in vaadin-shared-deps --> + <exclude name="com/google/gwt/thirdparty/streamhtmlparser/**" /> + <exclude name="org/w3c/flute/**" /> + + <!-- external dependencies --> + <exclude name="javax/servlet/**" /> + <exclude name="org/w3c/css/sac/**" /> + </fileset> + <!-- GWT Elemental --> + <fileset dir="${gwt.elemental.jar.files}"> + <exclude name="META-INF/**" /> + </fileset> + </union> + + <union id="shared.gwt.includes"> + <fileset dir="${gwt.user.jar.files}"> + <!-- Shared files from user --> + <include name="com/google/gwt/*/shared/**" /> + <include name="com/google/gwt/*/*/shared/**" /> + <include name="com/google/web/bindery/*/shared/**" /> + <include name="com/google/gwt/user/client/rpc/IsSerializable.*" /> + + </fileset> + </union> + + <union id="server.gwt.includes"> + <fileset dir="${gwt.user.jar.files}"> + <!-- Server files from gwt-user --> + <include name="com/google/gwt/*/server/**" /> + </fileset> + </union> </project> diff --git a/ivy-taskdefs.xml b/ivy-taskdefs.xml index 64d5ec1be1..3c04e5a051 100644 --- a/ivy-taskdefs.xml +++ b/ivy-taskdefs.xml @@ -1,24 +1,24 @@ <ivy-module version="2.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd"> - <info organisation="com.vaadin" module="vaadin" /> - <configurations> - <conf name="taskdefs" description="Ant task definitions" - visibility="private" /> - </configurations> - <publications /> - <dependencies> - <!-- Ant tasks --> - <dependency org="ant-contrib" name="ant-contrib" rev="1.0b3" - conf="taskdefs ->master" /> - <dependency org="org.apache.maven" name="maven-ant-tasks" - rev="2.0.10" conf="taskdefs ->master" /> - <dependency org="com.googlecode.jarjar" name="jarjar" rev="1.3" - conf="taskdefs ->master" /> - <dependency org="com.puppycrawl.tools" name="checkstyle" - rev="5.6" /> - </dependencies> + <info organisation="com.vaadin" module="vaadin" /> + <configurations> + <conf name="taskdefs" description="Ant task definitions" + visibility="private" /> + </configurations> + <publications /> + <dependencies> + <!-- Ant tasks --> + <dependency org="ant-contrib" name="ant-contrib" rev="1.0b3" + conf="taskdefs ->master" /> + <dependency org="org.apache.maven" name="maven-ant-tasks" + rev="2.0.10" conf="taskdefs ->master" /> + <dependency org="com.googlecode.jarjar" name="jarjar" + rev="1.3" conf="taskdefs ->master" /> + <dependency org="com.puppycrawl.tools" name="checkstyle" + rev="5.6" /> + </dependencies> </ivy-module> diff --git a/ivysettings.xml b/ivysettings.xml index 288eae9036..6c230b9fd8 100644 --- a/ivysettings.xml +++ b/ivysettings.xml @@ -16,12 +16,13 @@ pattern="${user.home}/.m2/repository/[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]" /> </filesystem> <dual name="custom-smartsprites"> - <filesystem name="smartsprites-ivy"> - <ivy pattern="${ivy.settings.dir}/theme-compiler/ivymodule/[module]-ivy-[revision].xml" /> - </filesystem> + <url name="smartsprites-ivy"> + <ivy + pattern="http://vaadin.com/download/external/[module]-ivy-[revision].xml" /> + </url> <url name="smartsprites-artifact"> <artifact - pattern="http://dev.vaadin.com/svn/versions/6.8/build/smartsprites/lib/[artifact](-[revision]).[ext]" /> + pattern="http://vaadin.com/download/external/[artifact](-[revision]).[ext]" /> </url> </dual> <filesystem name="build-temp"> @@ -32,9 +33,9 @@ </filesystem> </resolvers> <modules> - <!-- IT Mill patched SmartSprites --> + <!-- Custom SmartSprites until 0.2.10 is released --> <module organisation="com.carrotsearch" name="smartsprites" - revision="0.2.3-itmill" resolver="custom-smartsprites" /> + revision="0.2.10-vaadin" resolver="custom-smartsprites" /> <module organisation="com.vaadin" name="vaadin-buildhelpers" resolver="build-temp" /> <module organisation="com.vaadin" name="vaadin-shared" diff --git a/publish.xml b/publish.xml index 61638851cd..e979ec1ca9 100644 --- a/publish.xml +++ b/publish.xml @@ -1,74 +1,87 @@ <?xml version="1.0" encoding="UTF-8"?> -<project name="publish" basedir="." default="" xmlns:ivy="antlib:org.apache.ivy.ant" xmlns:antcontrib="antlib:net.sf.antcontrib" xmlns:artifact="antlib:org.apache.maven.artifact.ant"> - <include file="common.xml" as="common" /> - <include file="build.xml" as="vaadin" /> +<project name="publish" basedir="." default="" + xmlns:ivy="antlib:org.apache.ivy.ant" xmlns:antcontrib="antlib:net.sf.antcontrib" + xmlns:artifact="antlib:org.apache.maven.artifact.ant"> + <include file="common.xml" as="common" /> + <include file="build.xml" as="vaadin" /> - <!-- Dummy value as ivysettings-publish require a value --> - <property name="publish.sftp.keyfile" value="/dummy" /> - <property name="publish.sftp.ivy.pattern" value="dummy" /> + <!-- Dummy value as ivysettings-publish require a value --> + <property name="publish.sftp.keyfile" value="/dummy" /> + <property name="publish.sftp.ivy.pattern" value="dummy" /> - <ivy:settings file="ivysettings.xml" /> - <ivy:settings file="ivysettings-publish.xml" id="publish.settings" /> - <property file="publish.properties" /> + <ivy:settings file="ivysettings.xml" /> + <ivy:settings file="ivysettings-publish.xml" id="publish.settings" /> + <property file="publish.properties" /> - <available property="ant-jsch.present" file="${ant.home}/lib/ant-jsch.jar" /> - <available property="jsch.present" file="${ant.home}/lib/jsch-0.1.48.jar" /> - <fail unless="ant-jsch.present" message="Please install ant-jsch.jar into ANT_HOME/lib" /> - <fail unless="jsch.present" message="Please install jsch.jar into ANT_HOME/lib" /> + <available property="ant-jsch.present" file="${ant.home}/lib/ant-jsch.jar" /> + <available property="jsch.present" file="${ant.home}/lib/jsch-0.1.48.jar" /> + <fail unless="ant-jsch.present" message="Please install ant-jsch.jar into ANT_HOME/lib" /> + <fail unless="jsch.present" message="Please install jsch.jar into ANT_HOME/lib" /> - <target name="nightly.publish" depends="nightly.download.publish, nightly.maven.publish"> + <target name="nightly.publish" + depends="nightly.download.publish, nightly.maven.publish"> - </target> + </target> - <!-- Copies the nightly build artifacts to the download server. --> - <target name="nightly.tests.publish" if="nightly.tests.publish"> - <property name="file.war" location="result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${version}.war" /> - <property name="target" value="${nightly.tests.publish}/${vaadin.version.major}.${vaadin.version.minor}-${build.tag}.war" /> + <!-- Copies the nightly build artifacts to the download server. --> + <target name="nightly.tests.publish" if="nightly.tests.publish"> + <property name="file.war" + location="result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${version}.war" /> + <property name="target" + value="${nightly.tests.publish}/${vaadin.version.major}.${vaadin.version.minor}-${build.tag}.war" /> - <echo>Installing ${src} to ${target}</echo> + <echo>Installing ${src} to ${target}</echo> - <scp todir="${nightly.tests.publish}" file="${file.war}"> - </scp> - </target> + <scp todir="${nightly.tests.publish}" file="${file.war}"> + </scp> + </target> - <target name="nightly.download.publish"> - <antcontrib:foreach list="${modules.to.publish.to.download}" target="publish.module.to.download.site" param="module" /> - </target> + <target name="nightly.download.publish"> + <antcontrib:foreach list="${modules.to.publish.to.download}" + target="publish.module.to.download.site" param="module" /> + </target> - <target name="nightly.maven.publish"> - <antcontrib:foreach list="${modules.to.publish.to.maven}" target="publish.module.to.maven" param="module" /> - </target> + <target name="nightly.maven.publish"> + <antcontrib:foreach list="${modules.to.publish.to.maven}" + target="publish.module.to.maven" param="module" /> + </target> - <target name="publish.module.to.download.site"> - <fail unless="module" message="No module to publish defined" /> - <ivy:resolve file="${module}/ivy.xml" /> - <ivy:publish publishivy="false" settingsref="publish.settings" conf="*(public)" resolver="sftp-publish"> - <artifacts pattern="${ivy.settings.dir}/result/artifacts/[revision]/[module]/[artifact]-[revision](-[classifier]).[ext]" /> - </ivy:publish> - </target> + <target name="publish.module.to.download.site"> + <fail unless="module" message="No module to publish defined" /> + <ivy:resolve file="${module}/ivy.xml" /> + <ivy:publish publishivy="false" settingsref="publish.settings" + conf="*(public)" resolver="sftp-publish"> + <artifacts + pattern="${ivy.settings.dir}/result/artifacts/[revision]/[module]/[artifact]-[revision](-[classifier]).[ext]" /> + </ivy:publish> + </target> - <target name="publish.module.to.maven"> - <fail unless="module" message="No module to publish defined" /> - <property file="${gpg.passphrase.file}" /> + <target name="publish.module.to.maven"> + <fail unless="module" message="No module to publish defined" /> + <property file="${gpg.passphrase.file}" /> - <!-- Ivy should be able to handle this but this does not work at the moment - <ivy:resolve file="${module}/ivy.xml" /> - <ivy:publish pubrevision="7.0-SNAPSHOT" publishivy="false" settingsref="publish.settings" conf="*(public)" resolver="sonatype"> - <artifacts pattern="${ivy.settings.dir}/result/artifacts/${vaadin.version}/[module]/[artifact]-${vaadin.version}(-[classifier]).[ext]" /> - </ivy:publish> ---> - <property name="jar.file" location="result/artifacts/${vaadin.version}/vaadin-${module}/vaadin-${module}-${vaadin.version}.jar" /> - <property name="pom.file" location="result/artifacts/${vaadin.version}/vaadin-${module}/vaadin-${module}-${vaadin.version}.pom" /> + <!-- Ivy should be able to handle this but this does not work at + the moment <ivy:resolve file="${module}/ivy.xml" /> <ivy:publish pubrevision="7.0-SNAPSHOT" + publishivy="false" settingsref="publish.settings" conf="*(public)" resolver="sonatype"> + <artifacts pattern="${ivy.settings.dir}/result/artifacts/${vaadin.version}/[module]/[artifact]-${vaadin.version}(-[classifier]).[ext]" + /> </ivy:publish> --> + <property name="jar.file" + location="result/artifacts/${vaadin.version}/vaadin-${module}/vaadin-${module}-${vaadin.version}.jar" /> + <property name="pom.file" + location="result/artifacts/${vaadin.version}/vaadin-${module}/vaadin-${module}-${vaadin.version}.pom" /> - <artifact:mvn failonerror="true"> - <arg value="gpg:sign-and-deploy-file" /> - <sysproperty key="file" value="${jar.file}" /> - <sysproperty key="pomFile" value="${pom.file}" /> - <sysproperty key="repositoryId" value="${maven.snapshot.repository.id}" /> - <sysproperty key="url" value="${maven.snapshot.repository.url}" /> - <sysproperty key="gpg.passphrase" value="${gpg.passphrase}" /> - <sysproperty key="retryFailedDeploymentCount" value="10" /> - </artifact:mvn> - </target> + <artifact:mvn failonerror="true"> + <arg value="gpg:sign-and-deploy-file" /> + <sysproperty key="file" value="${jar.file}" /> + <sysproperty key="pomFile" value="${pom.file}" /> + <sysproperty key="repositoryId" + value="${maven.snapshot.repository.id}" /> + <sysproperty key="url" + value="${maven.snapshot.repository.url}" /> + <sysproperty key="gpg.passphrase" value="${gpg.passphrase}" /> + <sysproperty key="retryFailedDeploymentCount" + value="10" /> + </artifact:mvn> + </target> </project>
\ No newline at end of file diff --git a/push/build.xml b/push/build.xml index 95284e6e37..ad27599d36 100644 --- a/push/build.xml +++ b/push/build.xml @@ -1,74 +1,84 @@ <?xml version="1.0"?> -<project name="vaadin-push" basedir="." default="publish-local" xmlns:ivy="antlib:org.apache.ivy.ant"> - <description> - Meta package which defines dependencies needed for push - </description> - <include file="../build.xml" as="vaadin" /> - <include file="../common.xml" as="common" /> +<project name="vaadin-push" basedir="." default="publish-local" + xmlns:ivy="antlib:org.apache.ivy.ant"> + <description> + Meta package which defines dependencies needed for push + </description> + <include file="../build.xml" as="vaadin" /> + <include file="../common.xml" as="common" /> - <property name="module.name" value="vaadin-push" /> - <property name="module.symbolic" value="com.vaadin.push" /> - <property name="result.dir" location="result" /> - <property name="vaadinPush.js" location="${result.dir}/js/VAADIN/vaadinPush.js" /> - <path id="classpath.compile.custom" /> + <property name="module.name" value="vaadin-push" /> + <property name="module.symbolic" value="com.vaadin.push" /> + <property name="result.dir" location="result" /> + <property name="vaadinPush.js" location="${result.dir}/js/VAADIN/vaadinPush.js" /> - <union id="jar.includes"> - <fileset dir="${result.dir}/js"> - <include name="VAADIN/vaadinPush.js" /> - </fileset> - </union> + <!-- Keep the version number in sync with ivy.xml --> + <property name="atmosphere.version" value="1.0.13" /> + <property name="jquery.version" value="1.7.2" /> - <target name="vaadinPush.js"> - <mkdir dir="${result.dir}/js/VAADIN" /> - <property name="vaadinPush.js.output" location="${result.dir}/js/VAADIN/vaadinPush.js" /> - <property name="vaadinPush.js.combined.output" location="${result.dir}/js/VAADIN/push.combined.js" /> + <path id="classpath.compile.custom" /> - <loadfile srcfile="${vaadin.basedir}/WebContent/VAADIN/jquery-1.7.2.js" property="jquery.js.contents" /> - <loadfile srcfile="${vaadin.basedir}/WebContent/VAADIN/jquery.atmosphere.js" property="jquery.atmosphere.js.contents" /> - <loadfile srcfile="${vaadin.basedir}/WebContent/VAADIN/vaadinPush.js.tpl" property="vaadinPush.js.contents"> - <filterchain> - <replacetokens begintoken="@" endtoken="@"> - <token key="jquery.js" value="${jquery.js.contents}" /> - <token key="jquery.atmosphere.js" value="${jquery.atmosphere.js.contents}" /> - </replacetokens> - </filterchain> - </loadfile> - <echo file="${vaadinPush.js.combined.output}">${vaadinPush.js.contents}</echo> + <union id="jar.includes"> + <fileset dir="${result.dir}/js"> + <include name="VAADIN/vaadinPush.js" /> + </fileset> + </union> - <!-- Minify --> - <ivy:retrieve organisation="com.yahoo.platform.yui" module="yuicompressor" revision="2.4.7" inline="true" type="jar" pattern="${result.dir}/compressor.jar" /> - <java jar="${result.dir}/compressor.jar" fork="true"> - <arg value="-v"/> - <arg value="-o"/> - <arg file="${vaadinPush.js.output}"/> - <arg file="${vaadinPush.js.combined.output}"/> - </java> - </target> - - <target name="jar" depends="vaadinPush.js"> - <property name="server.osgi.import" value="" /> - <antcall target="common.jar"> - <param name="require-bundle" value="" /> - <param name="import-package" value="${server.osgi.import}" /> - <reference torefid="extra.jar.includes" refid="jar.includes" /> - </antcall> - </target> + <target name="vaadinPush.js"> + <mkdir dir="${result.dir}/js/VAADIN" /> + <property name="vaadinPush.js.output" location="${result.dir}/js/VAADIN/vaadinPush.js" /> + <property name="vaadinPush.js.combined.output" + location="${result.dir}/js/VAADIN/push.combined.js" /> - <target name="publish-local" depends="jar"> - <antcall target="common.sources.jar"> - <reference torefid="extra.jar.includes" refid="jar.includes" /> - </antcall> - <antcall target="common.javadoc.jar" /> - <antcall target="common.publish-local" /> - </target> + <loadfile + srcfile="${vaadin.basedir}/WebContent/VAADIN/jquery-${jquery.version}.js" + property="jquery.js.contents" /> + <loadfile + srcfile="${vaadin.basedir}/WebContent/VAADIN/jquery.atmosphere.js" + property="jquery.atmosphere.js.contents" /> + <loadfile + srcfile="${vaadin.basedir}/WebContent/VAADIN/vaadinPush.js.tpl" + property="vaadinPush.js.contents"> + <filterchain> + <replacetokens begintoken="@" endtoken="@"> + <token key="jquery.js" value="${jquery.js.contents}" /> + <token key="jquery.atmosphere.js" value="${jquery.atmosphere.js.contents}" /> + </replacetokens> + </filterchain> + </loadfile> + <echo file="${vaadinPush.js.combined.output}">${vaadinPush.js.contents}</echo> - <target name="clean"> - <antcall target="common.clean" /> - </target> - <target name="checkstyle"> - </target> + <!-- Minify --> + <ivy:retrieve organisation="com.yahoo.platform.yui" + module="yuicompressor" revision="2.4.7" inline="true" type="jar" + pattern="${result.dir}/compressor.jar" /> + <java jar="${result.dir}/compressor.jar" fork="true"> + <arg value="-v" /> + <arg value="-o" /> + <arg file="${vaadinPush.js.output}" /> + <arg file="${vaadinPush.js.combined.output}" /> + </java> + </target> - <target name="test" depends="checkstyle"> - </target> + <target name="jar" depends="vaadinPush.js"> + <antcall target="common.jar"> + <param name="require-bundle" + value="org.atmosphere.atmosphere-runtime;bundle-version="${atmosphere.version}";visibility:=reexport" /> + <reference torefid="extra.jar.includes" refid="jar.includes" /> + </antcall> + </target> + + <target name="publish-local" depends="jar"> + <antcall target="common.publish-local" /> + </target> + + <target name="clean"> + <antcall target="common.clean" /> + </target> + <target name="checkstyle"> + </target> + + <target name="test" depends="checkstyle"> + </target> </project>
\ No newline at end of file diff --git a/push/ivy.xml b/push/ivy.xml index 153c02e256..e2ba3a63f7 100644 --- a/push/ivy.xml +++ b/push/ivy.xml @@ -4,8 +4,7 @@ xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd" xmlns:m="http://ant.apache.org/ivy/maven"> - <info organisation="com.vaadin" module="vaadin-push" - revision="${vaadin.version}" /> + <info organisation="com.vaadin" module="vaadin-push" revision="${vaadin.version}" /> <configurations> <conf name="build" /> @@ -15,22 +14,21 @@ </configurations> <publications> <artifact type="jar" ext="jar" /> - <artifact type="source" ext="jar" m:classifier="sources" /> - <artifact type="javadoc" ext="jar" m:classifier="javadoc" /> + <!-- <artifact type="source" ext="jar" m:classifier="sources" /> + <artifact type="javadoc" ext="jar" m:classifier="javadoc" /> --> <artifact type="pom" ext="pom" /> </publications> <dependencies> - - <!-- API DEPENDENCIES --> - + <!--Servlet API version 2.4 --> <dependency org="javax.servlet" name="servlet-api" rev="2.4" conf="build-provided,ide,test -> default" /> - + <!-- Atmosphere --> - <dependency org="org.atmosphere" name="atmosphere-runtime" rev="1.0.12" - conf="build,ide,test -> default"> + <!-- Keep the version number in sync with build.xml --> + <dependency org="org.atmosphere" name="atmosphere-runtime" + rev="1.0.13" conf="build,ide,test -> default"> </dependency> </dependencies> diff --git a/push/src/org/atmosphere/cpr/AtmosphereFramework.java b/push/src/org/atmosphere/cpr/AtmosphereFramework.java deleted file mode 100644 index 62f867fc94..0000000000 --- a/push/src/org/atmosphere/cpr/AtmosphereFramework.java +++ /dev/null @@ -1,1779 +0,0 @@ -/* - * Copyright 2013 Jeanfrancois Arcand - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.atmosphere.cpr; - -import org.atmosphere.cache.UUIDBroadcasterCache; -import org.atmosphere.config.ApplicationConfiguration; -import org.atmosphere.config.AtmosphereHandlerConfig; -import org.atmosphere.config.AtmosphereHandlerProperty; -import org.atmosphere.config.FrameworkConfiguration; -import org.atmosphere.container.BlockingIOCometSupport; -import org.atmosphere.container.Tomcat7BIOSupportWithWebSocket; -import org.atmosphere.di.InjectorProvider; -import org.atmosphere.di.ServletContextHolder; -import org.atmosphere.di.ServletContextProvider; -import org.atmosphere.handler.AbstractReflectorAtmosphereHandler; -import org.atmosphere.handler.ReflectorServletProcessor; -import org.atmosphere.interceptor.AndroidAtmosphereInterceptor; -import org.atmosphere.interceptor.JSONPAtmosphereInterceptor; -import org.atmosphere.interceptor.JavaScriptProtocol; -import org.atmosphere.interceptor.OnDisconnectInterceptor; -import org.atmosphere.interceptor.SSEAtmosphereInterceptor; -import org.atmosphere.util.AtmosphereConfigReader; -import org.atmosphere.util.IntrospectionUtils; -import org.atmosphere.util.Version; -import org.atmosphere.websocket.DefaultWebSocketProcessor; -import org.atmosphere.websocket.WebSocket; -import org.atmosphere.websocket.WebSocketProtocol; -import org.atmosphere.websocket.protocol.SimpleHttpProtocol; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.Servlet; -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicBoolean; - -import static org.atmosphere.cpr.ApplicationConfig.ALLOW_QUERYSTRING_AS_REQUEST; -import static org.atmosphere.cpr.ApplicationConfig.ATMOSPHERE_HANDLER; -import static org.atmosphere.cpr.ApplicationConfig.ATMOSPHERE_HANDLER_MAPPING; -import static org.atmosphere.cpr.ApplicationConfig.ATMOSPHERE_HANDLER_PATH; -import static org.atmosphere.cpr.ApplicationConfig.BROADCASTER_CACHE; -import static org.atmosphere.cpr.ApplicationConfig.BROADCASTER_CLASS; -import static org.atmosphere.cpr.ApplicationConfig.BROADCASTER_FACTORY; -import static org.atmosphere.cpr.ApplicationConfig.BROADCASTER_LIFECYCLE_POLICY; -import static org.atmosphere.cpr.ApplicationConfig.BROADCAST_FILTER_CLASSES; -import static org.atmosphere.cpr.ApplicationConfig.DISABLE_ONSTATE_EVENT; -import static org.atmosphere.cpr.ApplicationConfig.PROPERTY_ATMOSPHERE_XML; -import static org.atmosphere.cpr.ApplicationConfig.PROPERTY_BLOCKING_COMETSUPPORT; -import static org.atmosphere.cpr.ApplicationConfig.PROPERTY_COMET_SUPPORT; -import static org.atmosphere.cpr.ApplicationConfig.PROPERTY_NATIVE_COMETSUPPORT; -import static org.atmosphere.cpr.ApplicationConfig.PROPERTY_SERVLET_MAPPING; -import static org.atmosphere.cpr.ApplicationConfig.PROPERTY_SESSION_SUPPORT; -import static org.atmosphere.cpr.ApplicationConfig.PROPERTY_USE_STREAM; -import static org.atmosphere.cpr.ApplicationConfig.RESUME_AND_KEEPALIVE; -import static org.atmosphere.cpr.ApplicationConfig.SUSPENDED_ATMOSPHERE_RESOURCE_UUID; -import static org.atmosphere.cpr.ApplicationConfig.WEBSOCKET_PROCESSOR; -import static org.atmosphere.cpr.ApplicationConfig.WEBSOCKET_PROTOCOL; -import static org.atmosphere.cpr.ApplicationConfig.WEBSOCKET_SUPPORT; -import static org.atmosphere.cpr.FrameworkConfig.ATMOSPHERE_CONFIG; -import static org.atmosphere.cpr.FrameworkConfig.HAZELCAST_BROADCASTER; -import static org.atmosphere.cpr.FrameworkConfig.JERSEY_BROADCASTER; -import static org.atmosphere.cpr.FrameworkConfig.JERSEY_CONTAINER; -import static org.atmosphere.cpr.FrameworkConfig.JGROUPS_BROADCASTER; -import static org.atmosphere.cpr.FrameworkConfig.JMS_BROADCASTER; -import static org.atmosphere.cpr.FrameworkConfig.REDIS_BROADCASTER; -import static org.atmosphere.cpr.FrameworkConfig.WRITE_HEADERS; -import static org.atmosphere.cpr.FrameworkConfig.XMPP_BROADCASTER; -import static org.atmosphere.cpr.HeaderConfig.ATMOSPHERE_POST_BODY; -import static org.atmosphere.cpr.HeaderConfig.X_ATMOSPHERE_TRACKING_ID; -import static org.atmosphere.websocket.WebSocket.WEBSOCKET_SUSPEND; - -/** - * The {@link AtmosphereFramework} is the entry point for the framework. This class can be used to from Servlet/filter - * to dispatch {@link AtmosphereRequest} and {@link AtmosphereResponse}. The framework can also be configured using - * the setXXX method. The life cycle of this class is - * <blockquote><pre> - * AtmosphereFramework f = new AtmosphereFramework(); - * f.init(); - * f.doCometSupport(AtmosphereRequest, AtmosphereResource); - * f.destroy(); - * </pre></blockquote> - * - * @author Jeanfrancois Arcand - */ -public class AtmosphereFramework implements ServletContextProvider { - public static final String DEFAULT_ATMOSPHERE_CONFIG_PATH = "/META-INF/atmosphere.xml"; - public static final String DEFAULT_LIB_PATH = "/WEB-INF/lib/"; - public static final String MAPPING_REGEX = "[a-zA-Z0-9-&.*=@~;\\?]+"; - - protected static final Logger logger = LoggerFactory.getLogger(AtmosphereFramework.class); - - protected final List<String> broadcasterFilters = new ArrayList<String>(); - protected final List<AsyncSupportListener> asyncSupportListeners = new ArrayList<AsyncSupportListener>(); - protected final ArrayList<String> possibleComponentsCandidate = new ArrayList<String>(); - protected final HashMap<String, String> initParams = new HashMap<String, String>(); - protected final AtmosphereConfig config; - protected final AtomicBoolean isCometSupportConfigured = new AtomicBoolean(false); - protected final boolean isFilter; - protected final Map<String, AtmosphereHandlerWrapper> atmosphereHandlers = new ConcurrentHashMap<String, AtmosphereHandlerWrapper>(); - protected final ConcurrentLinkedQueue<String> broadcasterTypes = new ConcurrentLinkedQueue<String>(); - - protected boolean useNativeImplementation = false; - protected boolean useBlockingImplementation = false; - protected boolean useStreamForFlushingComments = false; - protected AsyncSupport asyncSupport; - protected String broadcasterClassName = DefaultBroadcaster.class.getName(); - protected boolean isCometSupportSpecified = false; - protected boolean isBroadcasterSpecified = false; - protected boolean isSessionSupportSpecified = false; - protected BroadcasterFactory broadcasterFactory; - protected String broadcasterFactoryClassName; - protected String broadcasterCacheClassName; - protected boolean webSocketEnabled = true; - protected String broadcasterLifeCyclePolicy = "NEVER"; - protected String webSocketProtocolClassName = SimpleHttpProtocol.class.getName(); - protected WebSocketProtocol webSocketProtocol; - protected String handlersPath = "/WEB-INF/classes/"; - protected ServletConfig servletConfig; - protected boolean autoDetectHandlers = true; - private boolean hasNewWebSocketProtocol = false; - protected String atmosphereDotXmlPath = DEFAULT_ATMOSPHERE_CONFIG_PATH; - protected final LinkedList<AtmosphereInterceptor> interceptors = new LinkedList<AtmosphereInterceptor>(); - protected boolean scanDone = false; - protected String annotationProcessorClassName = "org.atmosphere.cpr.DefaultAnnotationProcessor"; - protected final List<BroadcasterListener> broadcasterListeners = new ArrayList<BroadcasterListener>(); - protected String webSocketProcessorClassName = DefaultWebSocketProcessor.class.getName(); - protected String libPath = DEFAULT_LIB_PATH; - protected boolean isInit; - protected boolean sharedThreadPools = true; - - public static final class AtmosphereHandlerWrapper { - - public final AtmosphereHandler atmosphereHandler; - public Broadcaster broadcaster; - public String mapping; - public List<AtmosphereInterceptor> interceptors = Collections.<AtmosphereInterceptor>emptyList(); - - public AtmosphereHandlerWrapper(BroadcasterFactory broadcasterFactory, AtmosphereHandler atmosphereHandler, String mapping) { - this.atmosphereHandler = atmosphereHandler; - try { - if (broadcasterFactory != null) { - this.broadcaster = broadcasterFactory.lookup(mapping, true); - } else { - this.mapping = mapping; - } - } catch (Exception t) { - throw new RuntimeException(t); - } - } - - public AtmosphereHandlerWrapper(AtmosphereHandler atmosphereHandler, Broadcaster broadcaster) { - this.atmosphereHandler = atmosphereHandler; - this.broadcaster = broadcaster; - } - - @Override - public String toString() { - return "AtmosphereHandlerWrapper{ atmosphereHandler=" + atmosphereHandler + ", broadcaster=" + - broadcaster + " }"; - } - } - - /** - * Create an AtmosphereFramework. - */ - public AtmosphereFramework() { - this(false, true); - } - - /** - * Create an AtmosphereFramework and initialize it via {@link AtmosphereFramework#init(javax.servlet.ServletConfig)} - */ - public AtmosphereFramework(ServletConfig sc) throws ServletException { - this(false, true); - init(sc); - } - - /** - * Create an AtmosphereFramework. - * - * @param isFilter true if this instance is used as an {@link AtmosphereFilter} - */ - public AtmosphereFramework(boolean isFilter, boolean autoDetectHandlers) { - this.isFilter = isFilter; - this.autoDetectHandlers = autoDetectHandlers; - readSystemProperties(); - populateBroadcasterType(); - config = new AtmosphereConfig(this); - } - - /** - * The order of addition is quite important here. - */ - private void populateBroadcasterType() { - broadcasterTypes.add(HAZELCAST_BROADCASTER); - broadcasterTypes.add(XMPP_BROADCASTER); - broadcasterTypes.add(REDIS_BROADCASTER); - broadcasterTypes.add(JGROUPS_BROADCASTER); - broadcasterTypes.add(JMS_BROADCASTER); - } - - /** - * Add an {@link AtmosphereHandler} serviced by the {@link Servlet} - * This API is exposed to allow embedding an Atmosphere application. - * - * @param mapping The servlet mapping (servlet path) - * @param h implementation of an {@link AtmosphereHandler} - * @param l An attay of {@link AtmosphereInterceptor} - */ - public AtmosphereFramework addAtmosphereHandler(String mapping, AtmosphereHandler h, List<AtmosphereInterceptor> l) { - if (!mapping.startsWith("/")) { - mapping = "/" + mapping; - } - - AtmosphereHandlerWrapper w = new AtmosphereHandlerWrapper(broadcasterFactory, h, mapping); - w.interceptors = l; - addMapping(mapping, w); - - logger.info("Installed AtmosphereHandler {} mapped to context-path: {}", h.getClass().getName(), mapping); - if (l.size() > 0) { - logger.info("Installed AtmosphereInterceptor {} mapped to AtmosphereHandler {}", l, h.getClass().getName()); - } - return this; - } - - /** - * Add an {@link AtmosphereHandler} serviced by the {@link Servlet} - * This API is exposed to allow embedding an Atmosphere application. - * - * @param mapping The servlet mapping (servlet path) - * @param h implementation of an {@link AtmosphereHandler} - */ - public AtmosphereFramework addAtmosphereHandler(String mapping, AtmosphereHandler h) { - addAtmosphereHandler(mapping, h, Collections.<AtmosphereInterceptor>emptyList()); - return this; - } - - private AtmosphereFramework addMapping(String path, AtmosphereHandlerWrapper w) { - // We are using JAXRS mapping algorithm. - if (path.contains("*")) { - path = path.replace("*", MAPPING_REGEX); - } - - if (path.endsWith("/")) { - path = path + MAPPING_REGEX; - } - - InjectorProvider.getInjector().inject(w.atmosphereHandler); - atmosphereHandlers.put(path, w); - return this; - } - - /** - * Add an {@link AtmosphereHandler} serviced by the {@link Servlet} - * This API is exposed to allow embedding an Atmosphere application. - * - * @param mapping The servlet mapping (servlet path) - * @param h implementation of an {@link AtmosphereHandler} - * @param broadcasterId The {@link Broadcaster#getID} value. - * @param l An attay of {@link AtmosphereInterceptor} - */ - public AtmosphereFramework addAtmosphereHandler(String mapping, AtmosphereHandler h, String broadcasterId, List<AtmosphereInterceptor> l) { - if (!mapping.startsWith("/")) { - mapping = "/" + mapping; - } - - AtmosphereHandlerWrapper w = new AtmosphereHandlerWrapper(broadcasterFactory, h, mapping); - w.broadcaster.setID(broadcasterId); - w.interceptors = l; - addMapping(mapping, w); - logger.info("Installed AtmosphereHandler {} mapped to context-path: {}", h.getClass().getName(), mapping); - if (l.size() > 0) { - logger.info("Installed AtmosphereInterceptor {} mapped to AtmosphereHandler {}", l, h.getClass().getName()); - } - return this; - } - - /** - * Add an {@link AtmosphereHandler} serviced by the {@link Servlet} - * This API is exposed to allow embedding an Atmosphere application. - * - * @param mapping The servlet mapping (servlet path) - * @param h implementation of an {@link AtmosphereHandler} - * @param broadcasterId The {@link Broadcaster#getID} value. - */ - public AtmosphereFramework addAtmosphereHandler(String mapping, AtmosphereHandler h, String broadcasterId) { - addAtmosphereHandler(mapping, h, broadcasterId, Collections.<AtmosphereInterceptor>emptyList()); - return this; - } - - /** - * Add an {@link AtmosphereHandler} serviced by the {@link Servlet} - * This API is exposed to allow embedding an Atmosphere application. - * - * @param mapping The servlet mapping (servlet path) - * @param h implementation of an {@link AtmosphereHandler} - * @param broadcaster The {@link Broadcaster} associated with AtmosphereHandler. - * @param l An attay of {@link AtmosphereInterceptor} - */ - public AtmosphereFramework addAtmosphereHandler(String mapping, AtmosphereHandler h, Broadcaster broadcaster, List<AtmosphereInterceptor> l) { - if (!mapping.startsWith("/")) { - mapping = "/" + mapping; - } - - AtmosphereHandlerWrapper w = new AtmosphereHandlerWrapper(h, broadcaster); - w.interceptors = l; - - addMapping(mapping, w); - logger.info("Installed AtmosphereHandler {} mapped to context-path: {}", h.getClass().getName(), mapping); - if (l.size() > 0) { - logger.info("Installed AtmosphereInterceptor {} mapped to AtmosphereHandler {}", l, h.getClass().getName()); - } - return this; - } - - /** - * Add an {@link AtmosphereHandler} serviced by the {@link Servlet} - * This API is exposed to allow embedding an Atmosphere application. - * - * @param mapping The servlet mapping (servlet path) - * @param h implementation of an {@link AtmosphereHandler} - * @param broadcaster The {@link Broadcaster} associated with AtmosphereHandler. - */ - public AtmosphereFramework addAtmosphereHandler(String mapping, AtmosphereHandler h, Broadcaster broadcaster) { - addAtmosphereHandler(mapping, h, broadcaster, Collections.<AtmosphereInterceptor>emptyList()); - return this; - } - - /** - * Remove an {@link AtmosphereHandler} - * - * @param mapping the mapping used when invoking {@link #addAtmosphereHandler(String, AtmosphereHandler)}; - * @return true if removed - */ - public AtmosphereFramework removeAtmosphereHandler(String mapping) { - - if (mapping.endsWith("/")) { - mapping += MAPPING_REGEX; - } - - atmosphereHandlers.remove(mapping); - return this; - } - - /** - * Remove all {@link AtmosphereHandler} - */ - public AtmosphereFramework removeAllAtmosphereHandler() { - atmosphereHandlers.clear(); - return this; - } - - /** - * Remove all init parameters. - */ - public AtmosphereFramework removeAllInitParams() { - initParams.clear(); - return this; - } - - /** - * Add init-param like if they were defined in web.xml - * - * @param name The name - * @param value The value - */ - public AtmosphereFramework addInitParameter(String name, String value) { - initParams.put(name, value); - return this; - } - - protected void readSystemProperties() { - if (System.getProperty(PROPERTY_NATIVE_COMETSUPPORT) != null) { - useNativeImplementation = Boolean - .parseBoolean(System.getProperty(PROPERTY_NATIVE_COMETSUPPORT)); - isCometSupportSpecified = true; - } - - if (System.getProperty(PROPERTY_BLOCKING_COMETSUPPORT) != null) { - useBlockingImplementation = Boolean - .parseBoolean(System.getProperty(PROPERTY_BLOCKING_COMETSUPPORT)); - isCometSupportSpecified = true; - } - atmosphereDotXmlPath = System.getProperty(PROPERTY_ATMOSPHERE_XML, atmosphereDotXmlPath); - - if (System.getProperty(DISABLE_ONSTATE_EVENT) != null) { - initParams.put(DISABLE_ONSTATE_EVENT, System.getProperty(DISABLE_ONSTATE_EVENT)); - } - } - - /** - * Path specific container using their own property. - */ - public void patchContainer() { - System.setProperty("org.apache.catalina.STRICT_SERVLET_COMPLIANCE", "false"); - } - - /** - * Initialize the AtmosphereFramework. Invoke that method after having properly configured this class using the setter. - */ - public AtmosphereFramework init() { - try { - init(new ServletConfig() { - - @Override - public String getServletName() { - return "AtmosphereFramework"; - } - - @Override - public ServletContext getServletContext() { - return (ServletContext) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{ServletContext.class}, - new InvocationHandler() { - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - logger.trace("Method {} not supported", method.getName()); - return null; - } - }); - } - - @Override - public String getInitParameter(String name) { - return initParams.get(name); - } - - @Override - public Enumeration<String> getInitParameterNames() { - return Collections.enumeration(initParams.values()); - } - }); - } catch (ServletException e) { - logger.error("", e); - } - return this; - } - - /** - * Initialize the AtmosphereFramework using the {@link ServletContext} - * - * @param sc the {@link ServletContext} - */ - public AtmosphereFramework init(final ServletConfig sc) throws ServletException { - - if (isInit) return this; - - try { - ServletContextHolder.register(this); - - ServletConfig scFacade = new ServletConfig() { - - public String getServletName() { - return sc.getServletName(); - } - - public ServletContext getServletContext() { - return sc.getServletContext(); - } - - public String getInitParameter(String name) { - String param = initParams.get(name); - if (param == null) { - return sc.getInitParameter(name); - } - return param; - } - - public Enumeration<String> getInitParameterNames() { - Enumeration en = sc.getInitParameterNames(); - while (en.hasMoreElements()) { - String name = (String) en.nextElement(); - if (!initParams.containsKey(name)) { - initParams.put(name, sc.getInitParameter(name)); - } - } - return Collections.enumeration(initParams.keySet()); - } - }; - this.servletConfig = scFacade; - asyncSupportListener(new AsyncSupportListenerAdapter()); - - autoConfigureService(scFacade.getServletContext()); - patchContainer(); - doInitParams(scFacade); - doInitParamsForWebSocket(scFacade); - configureBroadcaster(); - loadConfiguration(scFacade); - initWebSocket(); - - autoDetectContainer(); - configureWebDotXmlAtmosphereHandler(sc); - asyncSupport.init(scFacade); - initAtmosphereHandler(scFacade); - configureAtmosphereInterceptor(sc); - - if (broadcasterCacheClassName == null) { - logger.warn("No BroadcasterCache configured. Broadcasted message between client reconnection will be LOST. " + - "It is recommended to configure the {}", UUIDBroadcasterCache.class.getName()); - } else { - logger.info("Using BroadcasterCache: {}", broadcasterCacheClassName); - } - - // http://java.net/jira/browse/ATMOSPHERE-157 - if (sc.getServletContext() != null) { - sc.getServletContext().setAttribute(BroadcasterFactory.class.getName(), broadcasterFactory); - } - - for (String i : broadcasterFilters) { - logger.info("Using BroadcastFilter: {}", i); - } - - String s = config.getInitParameter(ApplicationConfig.BROADCASTER_SHARABLE_THREAD_POOLS); - if (s != null) { - sharedThreadPools = Boolean.parseBoolean(s); - } - - logger.info("Shared ExecutorService supported: {}", sharedThreadPools); - logger.info("HttpSession supported: {}", config.isSupportSession()); - logger.info("Using BroadcasterFactory: {}", broadcasterFactory.getClass().getName()); - logger.info("Using WebSocketProcessor: {}", webSocketProcessorClassName); - logger.info("Using Broadcaster: {}", broadcasterClassName); - logger.info("Atmosphere Framework {} started.", Version.getRawVersion()); - - String showSupportMessage = config.getInitParameter("org.atmosphere.cpr.showSupportMessage"); - if (showSupportMessage == null || Boolean.parseBoolean(showSupportMessage)) { - logger.info("\n\n\tFor Commercial Support, visit \n\t{} " + - "or send an email to {}\n", "http://www.async-io.org/", "support@async-io.org"); - } - } catch (Throwable t) { - logger.error("Failed to initialize Atmosphere Framework", t); - - if (t instanceof ServletException) { - throw (ServletException) t; - } - - throw new ServletException(t); - } - isInit = true; - return this; - } - - /** - * Configure the list of {@link AtmosphereInterceptor}. - * - * @param sc a ServletConfig - */ - protected void configureAtmosphereInterceptor(ServletConfig sc) { - String s = sc.getInitParameter(ApplicationConfig.ATMOSPHERE_INTERCEPTORS); - if (s != null) { - String[] list = s.split(","); - for (String a : list) { - try { - AtmosphereInterceptor ai = (AtmosphereInterceptor) Thread.currentThread().getContextClassLoader() - .loadClass(a.trim()).newInstance(); - ai.configure(config); - interceptor(ai); - } catch (InstantiationException e) { - logger.warn("", e); - } catch (IllegalAccessException e) { - logger.warn("", e); - } catch (ClassNotFoundException e) { - logger.warn("", e); - } - } - } - - s = sc.getInitParameter(ApplicationConfig.DISABLE_ATMOSPHEREINTERCEPTOR); - if (s == null) { - // OnDisconnect - interceptors.addFirst(newAInterceptor(OnDisconnectInterceptor.class)); - // ADD Tracking ID Handshake - interceptors.addFirst(newAInterceptor(JavaScriptProtocol.class)); - // ADD JSONP support - interceptors.addFirst(newAInterceptor(JSONPAtmosphereInterceptor.class)); - // Add SSE support - interceptors.addFirst(newAInterceptor(SSEAtmosphereInterceptor.class)); - // Android 2.3.x streaming support - interceptors.addFirst(newAInterceptor(AndroidAtmosphereInterceptor.class)); - logger.info("Installed Default AtmosphereInterceptor {}. " + - "Set org.atmosphere.cpr.AtmosphereInterceptor.disableDefaults in your xml to disable them.", interceptors); - } - } - - protected AtmosphereInterceptor newAInterceptor(Class<? extends AtmosphereInterceptor> a) { - AtmosphereInterceptor ai = null; - try { - ai = (AtmosphereInterceptor) getClass().getClassLoader().loadClass(a.getName()).newInstance(); - ai.configure(config); - } catch (Exception ex) { - logger.warn("", ex); - } - return ai; - } - - protected void configureWebDotXmlAtmosphereHandler(ServletConfig sc) { - String s = sc.getInitParameter(ATMOSPHERE_HANDLER); - if (s != null) { - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - try { - - String mapping = sc.getInitParameter(ATMOSPHERE_HANDLER_MAPPING); - if (mapping == null) { - mapping = "/*"; - } - addAtmosphereHandler(mapping, (AtmosphereHandler) cl.loadClass(s).newInstance()); - } catch (Exception ex) { - logger.warn("Unable to load WebSocketHandle instance", ex); - } - } - } - - protected void configureBroadcaster() { - - try { - // Check auto supported one - if (isBroadcasterSpecified == false) { - broadcasterClassName = lookupDefaultBroadcasterType(broadcasterClassName); - } - - Class<? extends Broadcaster> bc = - (Class<? extends Broadcaster>) Thread.currentThread().getContextClassLoader() - .loadClass(broadcasterClassName); - if (broadcasterFactoryClassName != null) { - broadcasterFactory = (BroadcasterFactory) Thread.currentThread().getContextClassLoader() - .loadClass(broadcasterFactoryClassName).newInstance(); - } - - if (broadcasterFactory == null) { - broadcasterFactory = new DefaultBroadcasterFactory(bc, broadcasterLifeCyclePolicy, config); - } - - for (BroadcasterListener b : broadcasterListeners) { - broadcasterFactory.addBroadcasterListener(b); - } - - BroadcasterFactory.setBroadcasterFactory(broadcasterFactory, config); - InjectorProvider.getInjector().inject(broadcasterFactory); - - Iterator<Entry<String, AtmosphereHandlerWrapper>> i = atmosphereHandlers.entrySet().iterator(); - AtmosphereHandlerWrapper w; - Entry<String, AtmosphereHandlerWrapper> e; - while (i.hasNext()) { - e = i.next(); - w = e.getValue(); - - if (w.broadcaster == null) { - w.broadcaster = broadcasterFactory.get(w.mapping); - } else { - if (broadcasterCacheClassName != null) { - BroadcasterCache cache = (BroadcasterCache) Thread.currentThread().getContextClassLoader() - .loadClass(broadcasterCacheClassName).newInstance(); - InjectorProvider.getInjector().inject(cache); - w.broadcaster.getBroadcasterConfig().setBroadcasterCache(cache); - } - } - } - } catch (Exception ex) { - logger.error("Unable to configure Broadcaster/Factory/Cache", ex); - } - } - - protected void doInitParamsForWebSocket(ServletConfig sc) { - String s = sc.getInitParameter(WEBSOCKET_SUPPORT); - if (s != null) { - webSocketEnabled = Boolean.parseBoolean(s); - sessionSupport(false); - } - s = sc.getInitParameter(WEBSOCKET_PROTOCOL); - if (s != null) { - webSocketProtocolClassName = s; - } - - s = sc.getInitParameter(WEBSOCKET_PROCESSOR); - if (s != null) { - webSocketProcessorClassName = s; - } - } - - /** - * Read init param from web.xml and apply them. - * - * @param sc {@link ServletConfig} - */ - protected void doInitParams(ServletConfig sc) { - String s = sc.getInitParameter(PROPERTY_NATIVE_COMETSUPPORT); - if (s != null) { - useNativeImplementation = Boolean.parseBoolean(s); - if (useNativeImplementation) isCometSupportSpecified = true; - } - s = sc.getInitParameter(PROPERTY_BLOCKING_COMETSUPPORT); - if (s != null) { - useBlockingImplementation = Boolean.parseBoolean(s); - if (useBlockingImplementation) isCometSupportSpecified = true; - } - s = sc.getInitParameter(PROPERTY_USE_STREAM); - if (s != null) { - useStreamForFlushingComments = Boolean.parseBoolean(s); - } - s = sc.getInitParameter(PROPERTY_COMET_SUPPORT); - if (s != null) { - asyncSupport = new DefaultAsyncSupportResolver(config).newCometSupport(s); - isCometSupportSpecified = true; - } - s = sc.getInitParameter(BROADCASTER_CLASS); - if (s != null) { - broadcasterClassName = s; - isBroadcasterSpecified = true; - } - s = sc.getInitParameter(BROADCASTER_CACHE); - if (s != null) { - broadcasterCacheClassName = s; - } - s = sc.getInitParameter(PROPERTY_SESSION_SUPPORT); - if (s != null) { - config.setSupportSession(Boolean.valueOf(s)); - isSessionSupportSpecified = true; - } - s = sc.getInitParameter(DISABLE_ONSTATE_EVENT); - if (s != null) { - initParams.put(DISABLE_ONSTATE_EVENT, s); - } else { - initParams.put(DISABLE_ONSTATE_EVENT, "false"); - } - s = sc.getInitParameter(RESUME_AND_KEEPALIVE); - if (s != null) { - initParams.put(RESUME_AND_KEEPALIVE, s); - } - s = sc.getInitParameter(BROADCAST_FILTER_CLASSES); - if (s != null) { - broadcasterFilters.addAll(Arrays.asList(s.split(","))); - logger.info("Installing BroadcastFilter class(es) {}", s); - } - s = sc.getInitParameter(BROADCASTER_LIFECYCLE_POLICY); - if (s != null) { - broadcasterLifeCyclePolicy = s; - } - s = sc.getInitParameter(BROADCASTER_FACTORY); - if (s != null) { - broadcasterFactoryClassName = s; - } - s = sc.getInitParameter(ATMOSPHERE_HANDLER_PATH); - if (s != null) { - handlersPath = s; - } - s = sc.getInitParameter(PROPERTY_ATMOSPHERE_XML); - if (s != null) { - atmosphereDotXmlPath = s; - } - } - - public void loadConfiguration(ServletConfig sc) throws ServletException { - - if (!autoDetectHandlers) return; - - try { - URL url = sc.getServletContext().getResource(handlersPath); - URLClassLoader urlC = new URLClassLoader(new URL[]{url}, - Thread.currentThread().getContextClassLoader()); - loadAtmosphereDotXml(sc.getServletContext(). - getResourceAsStream(atmosphereDotXmlPath), urlC); - - if (atmosphereHandlers.size() == 0) { - autoDetectAtmosphereHandlers(sc.getServletContext(), urlC); - - if (atmosphereHandlers.size() == 0) { - detectSupportedFramework(sc); - } - } - - autoDetectWebSocketHandler(sc.getServletContext(), urlC); - } catch (Throwable t) { - throw new ServletException(t); - } - } - - /** - * Auto-detect Jersey when no atmosphere.xml file are specified. - * - * @param sc {@link ServletConfig} - * @return true if Jersey classes are detected - * @throws ClassNotFoundException - */ - protected boolean detectSupportedFramework(ServletConfig sc) throws ClassNotFoundException, IllegalAccessException, - InstantiationException, NoSuchMethodException, InvocationTargetException { - - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - String broadcasterClassNameTmp = null; - - try { - cl.loadClass(JERSEY_CONTAINER); - - if (!isBroadcasterSpecified) { - broadcasterClassNameTmp = lookupDefaultBroadcasterType(JERSEY_BROADCASTER); - - cl.loadClass(broadcasterClassNameTmp); - } - useStreamForFlushingComments = true; - } catch (Throwable t) { - logger.trace("", t); - return false; - } - - logger.warn("Missing META-INF/atmosphere.xml but found the Jersey runtime. Starting Jersey"); - - // Jersey will handle itself the headers. - initParams.put(WRITE_HEADERS, "false"); - - ReflectorServletProcessor rsp = new ReflectorServletProcessor(); - if (broadcasterClassNameTmp != null) broadcasterClassName = broadcasterClassNameTmp; - rsp.setServletClassName(JERSEY_CONTAINER); - sessionSupport(false); - initParams.put(DISABLE_ONSTATE_EVENT, "true"); - - String mapping = sc.getInitParameter(PROPERTY_SERVLET_MAPPING); - if (mapping == null) { - mapping = "/*"; - } - Class<? extends Broadcaster> bc = (Class<? extends Broadcaster>) cl.loadClass(broadcasterClassName); - - - if (broadcasterFactory != null) { - broadcasterFactory.destroy(); - } - broadcasterFactory = new DefaultBroadcasterFactory(bc, broadcasterLifeCyclePolicy, config); - BroadcasterFactory.setBroadcasterFactory(broadcasterFactory, config); - - for (BroadcasterListener b : broadcasterListeners) { - broadcasterFactory.addBroadcasterListener(b); - } - - Broadcaster b; - - try { - b = broadcasterFactory.get(bc, mapping); - } catch (IllegalStateException ex) { - logger.warn("Two Broadcaster's named {}. Renaming the second one to {}", mapping, sc.getServletName() + mapping); - b = broadcasterFactory.get(bc, sc.getServletName() + mapping); - } - - addAtmosphereHandler(mapping, rsp, b); - return true; - } - - protected String lookupDefaultBroadcasterType(String defaultB) { - for (String b : broadcasterTypes) { - try { - Class.forName(b); - return b; - } catch (ClassNotFoundException e) { - } - } - return defaultB; - } - - protected void sessionSupport(boolean sessionSupport) { - if (!isSessionSupportSpecified) { - config.setSupportSession(sessionSupport); - } else if (!config.isSupportSession()) { - // Don't turn off session support. Once it's on, leave it on. - config.setSupportSession(sessionSupport); - } - } - - /** - * Initialize {@link AtmosphereServletProcessor} - * - * @param sc the {@link ServletConfig} - * @throws javax.servlet.ServletException - */ - public void initAtmosphereHandler(ServletConfig sc) throws ServletException { - AtmosphereHandler a; - AtmosphereHandlerWrapper w; - for (Entry<String, AtmosphereHandlerWrapper> h : atmosphereHandlers.entrySet()) { - w = h.getValue(); - a = w.atmosphereHandler; - if (a instanceof AtmosphereServletProcessor) { - ((AtmosphereServletProcessor) a).init(sc); - } - } - - if (atmosphereHandlers.size() == 0 && !SimpleHttpProtocol.class.isAssignableFrom(webSocketProtocol.getClass())) { - logger.debug("Adding a void AtmosphereHandler mapped to /* to allow WebSocket application only"); - addAtmosphereHandler("/*", new AbstractReflectorAtmosphereHandler() { - @Override - public void onRequest(AtmosphereResource r) throws IOException { - logger.debug("No AtmosphereHandler defined."); - } - - @Override - public void destroy() { - } - }); - } - } - - protected void initWebSocket() { - if (webSocketProtocol == null) { - try { - webSocketProtocol = (WebSocketProtocol) Thread.currentThread().getContextClassLoader() - .loadClass(webSocketProtocolClassName).newInstance(); - logger.info("Installed WebSocketProtocol {} ", webSocketProtocolClassName); - } catch (Exception ex) { - try { - webSocketProtocol = (WebSocketProtocol) AtmosphereFramework.class.getClassLoader() - .loadClass(webSocketProtocolClassName).newInstance(); - logger.info("Installed WebSocketProtocol {} ", webSocketProtocolClassName); - } catch (Exception ex2) { - logger.error("Cannot load the WebSocketProtocol {}", getWebSocketProtocolClassName(), ex); - webSocketProtocol = new SimpleHttpProtocol(); - } - } - } - webSocketProtocol.configure(config); - } - - public AtmosphereFramework destroy() { - if (asyncSupport != null && AsynchronousProcessor.class.isAssignableFrom(asyncSupport.getClass())) { - ((AsynchronousProcessor) asyncSupport).shutdown(); - } - - // We just need one bc to shutdown the shared thread pool - for (Entry<String, AtmosphereHandlerWrapper> entry : atmosphereHandlers.entrySet()) { - AtmosphereHandlerWrapper handlerWrapper = entry.getValue(); - handlerWrapper.atmosphereHandler.destroy(); - } - - BroadcasterFactory factory = broadcasterFactory; - if (factory != null) { - factory.destroy(); - BroadcasterFactory.factory = null; - } - WebSocketProcessorFactory.getDefault().destroy(); - return this; - } - - /** - * Load AtmosphereHandler defined under META-INF/atmosphere.xml - * - * @param stream The input stream we read from. - * @param c The classloader - */ - protected void loadAtmosphereDotXml(InputStream stream, URLClassLoader c) - throws IOException, ServletException { - - if (stream == null) { - return; - } - - AtmosphereConfigReader.getInstance().parse(config, stream); - for (AtmosphereHandlerConfig atmoHandler : config.getAtmosphereHandlerConfig()) { - try { - AtmosphereHandler handler; - - if (!ReflectorServletProcessor.class.getName().equals(atmoHandler.getClassName())) { - handler = (AtmosphereHandler) c.loadClass(atmoHandler.getClassName()).newInstance(); - } else { - handler = new ReflectorServletProcessor(); - } - - logger.info("Installed AtmosphereHandler {} mapped to context-path: {}", handler, atmoHandler.getContextRoot()); - - for (ApplicationConfiguration a : atmoHandler.getApplicationConfig()) { - initParams.put(a.getParamName(), a.getParamValue()); - } - - for (FrameworkConfiguration a : atmoHandler.getFrameworkConfig()) { - initParams.put(a.getParamName(), a.getParamValue()); - } - - for (AtmosphereHandlerProperty handlerProperty : atmoHandler.getProperties()) { - - if (handlerProperty.getValue() != null && handlerProperty.getValue().indexOf("jersey") != -1) { - initParams.put(DISABLE_ONSTATE_EVENT, "true"); - useStreamForFlushingComments = true; - broadcasterClassName = lookupDefaultBroadcasterType(JERSEY_BROADCASTER); - broadcasterFactory = null; - configureBroadcaster(); - } - - IntrospectionUtils.setProperty(handler, handlerProperty.getName(), handlerProperty.getValue()); - IntrospectionUtils.addProperty(handler, handlerProperty.getName(), handlerProperty.getValue()); - } - - sessionSupport(Boolean.valueOf(atmoHandler.getSupportSession())); - - String broadcasterClass = atmoHandler.getBroadcaster(); - Broadcaster b; - /** - * If there is more than one AtmosphereHandler defined, their Broadcaster - * may clash each other with the BroadcasterFactory. In that case we will use the - * last one defined. - */ - if (broadcasterClass != null) { - broadcasterClassName = broadcasterClass; - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - Class<? extends Broadcaster> bc = (Class<? extends Broadcaster>) cl.loadClass(broadcasterClassName); - broadcasterFactory = new DefaultBroadcasterFactory(bc, broadcasterLifeCyclePolicy, config); - BroadcasterFactory.setBroadcasterFactory(broadcasterFactory, config); - } - - b = broadcasterFactory.lookup(atmoHandler.getContextRoot(), true); - - AtmosphereHandlerWrapper wrapper = new AtmosphereHandlerWrapper(handler, b); - addMapping(atmoHandler.getContextRoot(), wrapper); - - String bc = atmoHandler.getBroadcasterCache(); - if (bc != null) { - broadcasterCacheClassName = bc; - } - - if (atmoHandler.getCometSupport() != null) { - asyncSupport = (AsyncSupport) c.loadClass(atmoHandler.getCometSupport()) - .getDeclaredConstructor(new Class[]{AtmosphereConfig.class}) - .newInstance(new Object[]{config}); - } - - if (atmoHandler.getBroadcastFilterClasses() != null) { - broadcasterFilters.addAll(atmoHandler.getBroadcastFilterClasses()); - } - - List<AtmosphereInterceptor> l = new ArrayList<AtmosphereInterceptor>(); - if (atmoHandler.getAtmosphereInterceptorClasses() != null) { - for (String a : atmoHandler.getAtmosphereInterceptorClasses()) { - try { - AtmosphereInterceptor ai = (AtmosphereInterceptor) c.loadClass(a).newInstance(); - ai.configure(config); - l.add(ai); - } catch (Throwable e) { - logger.warn("", e); - } - } - } - wrapper.interceptors = l; - if (l.size() > 0) { - logger.info("Installed AtmosphereInterceptor {} mapped to AtmosphereHandler {}", l, atmoHandler.getClassName()); - } - } catch (Throwable t) { - logger.warn("Unable to load AtmosphereHandler class: " + atmoHandler.getClassName(), t); - throw new ServletException(t); - } - - } - } - - /** - * Set the {@link AsyncSupport} implementation. Make sure you don't set - * an implementation that only works on some Container. See {@link BlockingIOCometSupport} - * for an example. - * - * @param asyncSupport - */ - public AtmosphereFramework setAsyncSupport(AsyncSupport asyncSupport) { - this.asyncSupport = asyncSupport; - return this; - } - - /** - * @param asyncSupport - * @return - * @Deprecated - Use {@link #setAsyncSupport(AsyncSupport)} - */ - public AtmosphereFramework setCometSupport(AsyncSupport asyncSupport) { - return setAsyncSupport(asyncSupport); - } - - /** - * Return the current {@link AsyncSupport} - * - * @return the current {@link AsyncSupport} - */ - public AsyncSupport getAsyncSupport() { - return asyncSupport; - } - - /** - * Return the current {@link AsyncSupport} - * - * @return the current {@link AsyncSupport} - * @deprecated Use getAsyncSupport - */ - public AsyncSupport getCometSupport() { - return asyncSupport; - } - - /** - * Returns an instance of AsyncSupportResolver {@link AsyncSupportResolver} - * - * @return CometSupportResolver - */ - protected AsyncSupportResolver createAsyncSupportResolver() { - return new DefaultAsyncSupportResolver(config); - } - - - /** - * Auto detect the underlying Servlet Container we are running on. - */ - protected void autoDetectContainer() { - // Was defined in atmosphere.xml - if (getAsyncSupport() == null) { - setAsyncSupport(createAsyncSupportResolver() - .resolve(useNativeImplementation, useBlockingImplementation, webSocketEnabled)); - } - - logger.info("Atmosphere is using async support: {} running under container: {}", - getAsyncSupport().getClass().getName(), asyncSupport.getContainerName()); - } - - /** - * Auto detect instance of {@link AtmosphereHandler} in case META-INF/atmosphere.xml - * is missing. - * - * @param servletContext {@link ServletContext} - * @param classloader {@link URLClassLoader} to load the class. - * @throws java.net.MalformedURLException - * @throws java.net.URISyntaxException - */ - public void autoDetectAtmosphereHandlers(ServletContext servletContext, URLClassLoader classloader) - throws MalformedURLException, URISyntaxException { - - // If Handler has been added - if (atmosphereHandlers.size() > 0) return; - - logger.info("Auto detecting atmosphere handlers {}", handlersPath); - - String realPath = servletContext.getRealPath(handlersPath); - - // Weblogic bug - if (realPath == null) { - URL u = servletContext.getResource(handlersPath); - if (u == null) return; - realPath = u.getPath(); - } - - loadAtmosphereHandlersFromPath(classloader, realPath); - } - - public void loadAtmosphereHandlersFromPath(URLClassLoader classloader, String realPath) { - File file = new File(realPath); - - if (file.isDirectory()) { - getFiles(file); - scanDone = true; - - for (String className : possibleComponentsCandidate) { - try { - className = className.replace('\\', '/'); - className = className.replaceFirst("^.*/(WEB-INF|target)(?:/scala-[^/]+)?/(test-)?classes/(.*)\\.class", "$3").replace("/", "."); - Class<?> clazz = classloader.loadClass(className); - - if (AtmosphereHandler.class.isAssignableFrom(clazz)) { - AtmosphereHandler handler = (AtmosphereHandler) clazz.newInstance(); - InjectorProvider.getInjector().inject(handler); - addMapping("/" + handler.getClass().getSimpleName(), - new AtmosphereHandlerWrapper(broadcasterFactory, handler, "/" + handler.getClass().getSimpleName())); - logger.info("Installed AtmosphereHandler {} mapped to context-path: {}", handler, handler.getClass().getName()); - } - } catch (Throwable t) { - logger.trace("failed to load class as an AtmosphereHandler: " + className, t); - } - } - } - } - - /** - * Auto detect instance of {@link org.atmosphere.websocket.WebSocketHandler} in case META-INF/atmosphere.xml - * is missing. - * - * @param servletContext {@link ServletContext} - * @param classloader {@link URLClassLoader} to load the class. - * @throws java.net.MalformedURLException - * @throws java.net.URISyntaxException - */ - protected void autoDetectWebSocketHandler(ServletContext servletContext, URLClassLoader classloader) - throws MalformedURLException, URISyntaxException { - - if (hasNewWebSocketProtocol) return; - - logger.info("Auto detecting WebSocketHandler in {}", handlersPath); - - String realPath = servletContext.getRealPath(handlersPath); - - // Weblogic bug - if (realPath == null) { - URL u = servletContext.getResource(handlersPath); - if (u == null) return; - realPath = u.getPath(); - } - - loadWebSocketFromPath(classloader, realPath); - } - - protected void loadWebSocketFromPath(URLClassLoader classloader, String realPath) { - File file = new File(realPath); - - if (file.isDirectory()) { - getFiles(file); - scanDone = true; - - for (String className : possibleComponentsCandidate) { - try { - className = className.replace('\\', '/'); - className = className.replaceFirst("^.*/(WEB-INF|target)(?:/scala-[^/]+)?/(test-)?classes/(.*)\\.class", "$3").replace("/", "."); - Class<?> clazz = classloader.loadClass(className); - - if (WebSocketProtocol.class.isAssignableFrom(clazz)) { - webSocketProtocol = (WebSocketProtocol) clazz.newInstance(); - InjectorProvider.getInjector().inject(webSocketProtocol); - logger.info("Installed WebSocketProtocol {}", webSocketProtocol); - } - } catch (Throwable t) { - logger.trace("failed to load class as an WebSocketProtocol: " + className, t); - } - } - } - } - - - /** - * Get the list of possible candidate to load as {@link AtmosphereHandler} - * - * @param f the real path {@link File} - */ - private void getFiles(File f) { - if (scanDone) return; - - File[] files = f.listFiles(); - for (File test : files) { - if (test.isDirectory()) { - getFiles(test); - } else { - String clazz = test.getAbsolutePath(); - if (clazz.endsWith(".class")) { - possibleComponentsCandidate.add(clazz); - } - } - } - } - - /** - * Invoke the proprietary {@link AsyncSupport} - * - * @param req - * @param res - * @return an {@link Action} - * @throws IOException - * @throws ServletException - */ - public Action doCometSupport(AtmosphereRequest req, AtmosphereResponse res) throws IOException, ServletException { - req.setAttribute(BROADCASTER_FACTORY, broadcasterFactory); - req.setAttribute(PROPERTY_USE_STREAM, useStreamForFlushingComments); - req.setAttribute(BROADCASTER_CLASS, broadcasterClassName); - req.setAttribute(ATMOSPHERE_CONFIG, config); - - Action a = null; - try { - boolean skip = true; - String s = config.getInitParameter(ALLOW_QUERYSTRING_AS_REQUEST); - if (s != null) { - skip = Boolean.valueOf(s); - } - if (!skip || req.getAttribute(WEBSOCKET_SUSPEND) == null) { - Map<String, String> headers = configureQueryStringAsRequest(req); - String body = headers.remove(ATMOSPHERE_POST_BODY); - if (body != null && body.isEmpty()) { - body = null; - } - - req.headers(headers) - .method(body != null && req.getMethod().equalsIgnoreCase("GET") ? "POST" : req.getMethod()); - - if (body != null) { - req.body(body); - } - } - - s = req.getHeader(X_ATMOSPHERE_TRACKING_ID); - - // Lookup for websocket - if (s == null || s.equals("0")) { - String unique = config.getInitParameter(ApplicationConfig.UNIQUE_UUID_WEBSOCKET); - if (unique != null && Boolean.valueOf(unique)) { - s = (String) req.getAttribute(SUSPENDED_ATMOSPHERE_RESOURCE_UUID); - } - } - - if (s == null || s.equals("0")) { - s = UUID.randomUUID().toString(); - res.setHeader(X_ATMOSPHERE_TRACKING_ID, s); - } else { - // This may breaks 1.0.0 application because the WebSocket's associated AtmosphereResource will - // all have the same UUID, and retrieving the original one for WebSocket, so we don't set it at all. - // Null means it is not an HTTP request. - if (req.resource() == null) { - res.setHeader(X_ATMOSPHERE_TRACKING_ID, s); - } else if (req.getAttribute(WebSocket.WEBSOCKET_INITIATED) == null) { - // WebSocket reconnect, in case an application manually set the header - // (impossible to retrieve the headers normally with WebSocket or SSE) - res.setHeader(X_ATMOSPHERE_TRACKING_ID, s); - } - } - - if (req.getAttribute(SUSPENDED_ATMOSPHERE_RESOURCE_UUID) == null) { - req.setAttribute(SUSPENDED_ATMOSPHERE_RESOURCE_UUID, s); - } - - a = asyncSupport.service(req, res); - } catch (IllegalStateException ex) { - if (ex.getMessage() != null && (ex.getMessage().startsWith("Tomcat failed") || ex.getMessage().startsWith("JBoss failed"))) { - if (!isFilter) { - logger.warn("Failed using comet support: {}, error: {} Is the Nio or Apr Connector enabled?", asyncSupport.getClass().getName(), - ex.getMessage()); - } - logger.trace(ex.getMessage(), ex); - - AsyncSupport current = asyncSupport; - asyncSupport = asyncSupport.supportWebSocket() ? new Tomcat7BIOSupportWithWebSocket(config) : new BlockingIOCometSupport(config); - if (current instanceof AsynchronousProcessor) { - ((AsynchronousProcessor) current).shutdown(); - } - - asyncSupport.init(config.getServletConfig()); - logger.warn("Using " + asyncSupport.getClass().getName()); - - a = asyncSupport.service(req, res); - } else { - logger.error("AtmosphereFramework exception", ex); - throw ex; - } - } finally { - if (a != null) { - notify(a.type(), req, res); - } - - if (req != null && a != null && a.type() != Action.TYPE.SUSPEND) { - req.destroy(); - res.destroy(); - notify(Action.TYPE.DESTROYED, req, res); - } - } - return a; - } - - /** - * Return the default {@link Broadcaster} class name. - * - * @return the broadcasterClassName - */ - public String getDefaultBroadcasterClassName() { - return broadcasterClassName; - } - - /** - * Set the default {@link Broadcaster} class name - * - * @param bccn the broadcasterClassName to set - */ - public AtmosphereFramework setDefaultBroadcasterClassName(String bccn) { - broadcasterClassName = bccn; - return this; - } - - /** - * <tt>true</tt> if Atmosphere uses {@link AtmosphereResponse#getOutputStream()} - * by default for write operation. - * - * @return the useStreamForFlushingComments - */ - public boolean isUseStreamForFlushingComments() { - return useStreamForFlushingComments; - } - - /** - * Set to <tt>true</tt> so Atmosphere uses {@link AtmosphereResponse#getOutputStream()} - * by default for write operation. Default is false. - * - * @param useStreamForFlushingComments the useStreamForFlushingComments to set - */ - public AtmosphereFramework setUseStreamForFlushingComments(boolean useStreamForFlushingComments) { - this.useStreamForFlushingComments = useStreamForFlushingComments; - return this; - } - - /** - * Get the {@link BroadcasterFactory} which is used by Atmosphere to construct - * {@link Broadcaster} - * - * @return {@link BroadcasterFactory} - */ - public BroadcasterFactory getBroadcasterFactory() { - return broadcasterFactory; - } - - /** - * Set the {@link BroadcasterFactory} which is used by Atmosphere to construct - * {@link Broadcaster} - * - * @return {@link BroadcasterFactory} - */ - public AtmosphereFramework setBroadcasterFactory(final BroadcasterFactory broadcasterFactory) { - this.broadcasterFactory = broadcasterFactory; - configureBroadcaster(); - return this; - } - - /** - * Return the {@link org.atmosphere.cpr.BroadcasterCache} class name. - * - * @return the {@link org.atmosphere.cpr.BroadcasterCache} class name. - */ - public String getBroadcasterCacheClassName() { - return broadcasterCacheClassName; - } - - /** - * Set the {@link org.atmosphere.cpr.BroadcasterCache} class name. - * - * @param broadcasterCacheClassName - */ - public void setBroadcasterCacheClassName(String broadcasterCacheClassName) { - this.broadcasterCacheClassName = broadcasterCacheClassName; - configureBroadcaster(); - } - - /** - * Add a new Broadcaster class name AtmosphereServlet can use when initializing requests, and when - * atmosphere.xml broadcaster element is unspecified. - * - * @param broadcasterTypeString - */ - public AtmosphereFramework addBroadcasterType(String broadcasterTypeString) { - broadcasterTypes.add(broadcasterTypeString); - return this; - } - - public String getWebSocketProtocolClassName() { - return webSocketProtocolClassName; - } - - public AtmosphereFramework setWebSocketProtocolClassName(String webSocketProtocolClassName) { - hasNewWebSocketProtocol = true; - this.webSocketProtocolClassName = webSocketProtocolClassName; - return this; - } - - public Map<String, AtmosphereHandlerWrapper> getAtmosphereHandlers() { - return atmosphereHandlers; - } - - protected Map<String, String> configureQueryStringAsRequest(AtmosphereRequest request) { - Map<String, String> headers = new HashMap<String, String>(); - - Enumeration<String> e = request.getParameterNames(); - String s; - while (e.hasMoreElements()) { - s = e.nextElement(); - if (s.equalsIgnoreCase("Content-Type")) { - // Use the one set by the user first. - if (request.getContentType() == null || - !request.getContentType().equalsIgnoreCase(request.getParameter(s))) { - request.contentType(request.getParameter(s)); - } - } - headers.put(s, request.getParameter(s)); - } - logger.trace("Query String translated to headers {}", headers); - return headers; - } - - protected boolean isIECandidate(AtmosphereRequest request) { - String userAgent = request.getHeader("User-Agent"); - if (userAgent == null) return false; - - if (userAgent.contains("MSIE") || userAgent.contains(".NET")) { - // Now check the header - String transport = request.getHeader(HeaderConfig.X_ATMOSPHERE_TRANSPORT); - if (transport != null) { - return false; - } else { - return true; - } - } - return false; - } - - public WebSocketProtocol getWebSocketProtocol() { - // TODO: Spagetthi code, needs to rework. - // Make sure we initialized the WebSocketProtocol - initWebSocket(); - return webSocketProtocol; - } - - public boolean isUseNativeImplementation() { - return useNativeImplementation; - } - - public AtmosphereFramework setUseNativeImplementation(boolean useNativeImplementation) { - this.useNativeImplementation = useNativeImplementation; - return this; - } - - public boolean isUseBlockingImplementation() { - return useBlockingImplementation; - } - - public AtmosphereFramework setUseBlockingImplementation(boolean useBlockingImplementation) { - this.useBlockingImplementation = useBlockingImplementation; - return this; - } - - public String getAtmosphereDotXmlPath() { - return atmosphereDotXmlPath; - } - - public AtmosphereFramework setAtmosphereDotXmlPath(String atmosphereDotXmlPath) { - this.atmosphereDotXmlPath = atmosphereDotXmlPath; - return this; - } - - public String getHandlersPath() { - return handlersPath; - } - - public AtmosphereFramework setHandlersPath(String handlersPath) { - this.handlersPath = handlersPath; - return this; - } - - /** - * Return the location of the jars containing the application classes. Default is WEB-INF/lib - * - * @return the location of the jars containing the application classes. Default is WEB-INF/lib - */ - public String getLibPath() { - return libPath; - } - - /** - * Set the location of the jars containing the application. - * - * @param libPath the location of the jars containing the application. - * @return this - */ - public AtmosphereFramework setLibPath(String libPath) { - this.libPath = libPath; - return this; - } - - public String getWebSocketProcessorClassName() { - return webSocketProcessorClassName; - } - - public AtmosphereFramework setWebsocketProcessorClassName(String webSocketProcessorClassName) { - this.webSocketProcessorClassName = webSocketProcessorClassName; - return this; - } - - /** - * Add an {@link AtmosphereInterceptor} implementation. The adding order or {@link AtmosphereInterceptor} will be used, e.g - * the first added {@link AtmosphereInterceptor} will always be called first. - * - * @param c {@link AtmosphereInterceptor} - * @return this - */ - public AtmosphereFramework interceptor(AtmosphereInterceptor c) { - boolean found = false; - for (AtmosphereInterceptor interceptor : interceptors) { - if (interceptor.getClass().equals(c.getClass())) { - found = true; - break; - } - } - - if (!found) { - interceptors.addLast(c); - logger.info("Installed AtmosphereInterceptor {}. ", c); - } - return this; - } - - /** - * Return the list of {@link AtmosphereInterceptor} - * - * @return the list of {@link AtmosphereInterceptor} - */ - public LinkedList<AtmosphereInterceptor> interceptors() { - return interceptors; - } - - /** - * Set the {@link AnnotationProcessor} class name. - * - * @param annotationProcessorClassName the {@link AnnotationProcessor} class name. - * @return this - */ - public AtmosphereFramework annotationProcessorClassName(String annotationProcessorClassName) { - this.annotationProcessorClassName = annotationProcessorClassName; - return this; - } - - /** - * Add an {@link AsyncSupportListener} - * - * @param asyncSupportListener an {@link AsyncSupportListener} - * @return this; - */ - public AtmosphereFramework asyncSupportListener(AsyncSupportListener asyncSupportListener) { - asyncSupportListeners.add(asyncSupportListener); - return this; - } - - /** - * Return the list of an {@link AsyncSupportListener} - * - * @return - */ - public List<AsyncSupportListener> asyncSupportListeners() { - return asyncSupportListeners; - } - - /** - * Add {@link BroadcasterListener} to all created {@link Broadcaster} - */ - public AtmosphereFramework addBroadcasterListener(BroadcasterListener b) { - if (isInit) { - broadcasterFactory.addBroadcasterListener(b); - } else { - broadcasterListeners.add(b); - } - return this; - } - - /** - * Return a configured instance of {@link AtmosphereConfig} - * - * @return a configured instance of {@link AtmosphereConfig} - */ - public AtmosphereConfig getAtmosphereConfig() { - return config; - } - - @Override - public ServletContext getServletContext() { - return servletConfig.getServletContext(); - } - - public ServletConfig getServletConfig() { - return servletConfig; - } - - /** - * Return the list of {@link BroadcastFilter} - * - * @return the list of {@link BroadcastFilter - */ - public List<String> broadcasterFilters() { - return broadcasterFilters; - } - - /** - * Returns true if {@link java.util.concurrent.ExecutorService} shared amongst all components. - * - * @return true if {@link java.util.concurrent.ExecutorService} shared amongst all components. - */ - public boolean isShareExecutorServices() { - return sharedThreadPools; - } - - /** - * Set to true to have a {@link java.util.concurrent.ExecutorService} shared amongst all components. - * - * @param sharedThreadPools - * @return this - */ - public AtmosphereFramework shareExecutorServices(boolean sharedThreadPools) { - this.sharedThreadPools = sharedThreadPools; - return this; - } - - protected void autoConfigureService(ServletContext sc) throws IOException { - final ClassLoader cl = Thread.currentThread().getContextClassLoader(); - - String path = libPath != DEFAULT_LIB_PATH ? libPath : sc.getRealPath(handlersPath); - try { - AnnotationProcessor p = (AnnotationProcessor) cl.loadClass(annotationProcessorClassName).newInstance(); - logger.info("Atmosphere is using {} for processing annotation", annotationProcessorClassName); - - p.configure(this); - if (path != null) { - p.scan(new File(path)); - } - - String pathLibs = sc.getRealPath(DEFAULT_LIB_PATH); - if (pathLibs != null) { - File libFolder = new File(pathLibs); - File jars[] = libFolder.listFiles(new FilenameFilter() { - - @Override - public boolean accept(File arg0, String arg1) { - return arg1.endsWith(".jar"); - } - }); - - for (File file : jars) { - p.scan(file); - } - } - } catch (Throwable e) { - logger.debug("Atmosphere's Service Annotation Not Supported. Please add https://github.com/rmuller/infomas-asl as dependencies or your own AnnotationProcessor to support @Service"); - logger.trace("", e); - return; - } - } - - protected void notify(Action.TYPE type, AtmosphereRequest request, AtmosphereResponse response) { - for (AsyncSupportListener l : asyncSupportListeners()) { - try { - switch (type) { - case TIMEOUT: - l.onTimeout(request, response); - break; - case CANCELLED: - l.onClose(request, response); - break; - case SUSPEND: - l.onSuspend(request, response); - break; - case RESUME: - l.onSuspend(request, response); - break; - case DESTROYED: - l.onDestroyed(request, response); - break; - } - } catch (Throwable t) { - logger.warn("", t); - } - } - } -}
\ No newline at end of file diff --git a/server/build.xml b/server/build.xml index d61f412883..a812404862 100644 --- a/server/build.xml +++ b/server/build.xml @@ -1,59 +1,63 @@ <?xml version="1.0"?> -<project name="vaadin-server" basedir="." default="publish-local" xmlns:ivy="antlib:org.apache.ivy.ant"> - <description> - Compiles build helpers used when building other modules. - </description> - <include file="../common.xml" as="common" /> - <include file="../build.xml" as="vaadin" /> - <include file="../gwt-files.xml" as="gwtfiles" /> - - <!-- global properties --> - <property name="module.name" value="vaadin-server" /> - <property name="module.symbolic" value="com.vaadin.server" /> - <property name="result.dir" value="result" /> - <path id="classpath.compile.custom" /> - <path id="classpath.test.custom" /> - - <union id="jar.includes"> - <union refid="server.gwt.includes" /> - <fileset dir="${vaadin.basedir}/WebContent"> - <include name="VAADIN/vaadinBootstrap.js" /> - </fileset> - </union> - - <target name="jar"> - <property name="server.osgi.import" value="javax.servlet;version="2.4.0",javax.servlet.http;version="2.4.0",org.jsoup;version="1.6.3",org.jsoup.parser;version="1.6.3",org.jsoup.nodes;version="1.6.3",org.jsoup.helper;version="1.6.3",org.jsoup.safety;version="1.6.3",org.json;version="0.0.20080701"" /> - <antcall target="common.jar"> - <param name="require-bundle" value="com.vaadin.shared;bundle-version="${vaadin.version}""/> - <param name="import-package" value="${server.osgi.import}" /> - <param name="osgi.extra.package.prefixes" value="VAADIN" /> - <reference torefid="extra.jar.includes" refid="jar.includes" /> - </antcall> - </target> - - <target name="publish-local" depends="jar"> - <antcall target="common.sources.jar"> - <reference torefid="extra.jar.includes" refid="server.gwt.includes" /> - </antcall> - <antcall target="common.javadoc.jar" /> - - <antcall target="common.publish-local" /> - </target> - - <target name="clean"> - <antcall target="common.clean" /> - </target> - - <target name="checkstyle"> - <antcall target="common.checkstyle"> - <param name="cs.src" location="src" /> - </antcall> - </target> - - <target name="test" depends="checkstyle"> - <antcall target="common.test.run" /> - </target> +<project name="vaadin-server" basedir="." default="publish-local" + xmlns:ivy="antlib:org.apache.ivy.ant"> + <description> + Compiles build helpers used when building other modules. + </description> + <include file="../common.xml" as="common" /> + <include file="../build.xml" as="vaadin" /> + <include file="../gwt-files.xml" as="gwtfiles" /> + + <!-- global properties --> + <property name="module.name" value="vaadin-server" /> + <property name="module.symbolic" value="com.vaadin.server" /> + <property name="result.dir" value="result" /> + <path id="classpath.compile.custom" /> + <path id="classpath.test.custom" /> + + <union id="jar.includes"> + <union refid="server.gwt.includes" /> + <fileset dir="${vaadin.basedir}/WebContent"> + <include name="VAADIN/vaadinBootstrap.js" /> + </fileset> + </union> + + <target name="jar"> + <property name="server.osgi.import" + value="javax.servlet;version="2.4.0",javax.servlet.http;version="2.4.0",org.jsoup;version="1.6.3",org.jsoup.parser;version="1.6.3",org.jsoup.nodes;version="1.6.3",org.jsoup.helper;version="1.6.3",org.jsoup.safety;version="1.6.3",org.json;version="0.0.20080701"" /> + <property name="server.osgi.require" + value="com.vaadin.shared;bundle-version="${vaadin.version}",com.vaadin.push;bundle-version="${vaadin.version}";resolution:=optional" /> + <antcall target="common.jar"> + <param name="require-bundle" value="${server.osgi.require}" /> + <param name="import-package" value="${server.osgi.import}" /> + <param name="osgi.extra.package.prefixes" value="VAADIN" /> + <reference torefid="extra.jar.includes" refid="jar.includes" /> + </antcall> + </target> + + <target name="publish-local" depends="jar"> + <antcall target="common.sources.jar"> + <reference torefid="extra.jar.includes" refid="server.gwt.includes" /> + </antcall> + <antcall target="common.javadoc.jar" /> + + <antcall target="common.publish-local" /> + </target> + + <target name="clean"> + <antcall target="common.clean" /> + </target> + + <target name="checkstyle"> + <antcall target="common.checkstyle"> + <param name="cs.src" location="src" /> + </antcall> + </target> + + <target name="test" depends="checkstyle"> + <antcall target="common.test.run" /> + </target> </project> diff --git a/server/ivy.xml b/server/ivy.xml index 46d9e4c9f5..db7e953371 100644 --- a/server/ivy.xml +++ b/server/ivy.xml @@ -45,8 +45,8 @@ rev="${vaadin.version}" conf="build,test->build" /> <dependency org="com.vaadin" name="vaadin-theme-compiler" rev="${vaadin.version}" conf="build,test->build" /> - <dependency org="com.vaadin" name="vaadin-push" - rev="${vaadin.version}" conf="build-provided,test->build" /> + <dependency org="com.vaadin" name="vaadin-push" rev="${vaadin.version}" + conf="build-provided,test->build" /> <!-- Jsoup for BootstrapHandler --> <dependency org="org.jsoup" name="jsoup" rev="1.6.3" @@ -70,12 +70,10 @@ conf="test -> default" /> <dependency org="org.hibernate" name="hibernate-validator" rev="4.2.0.Final" conf="test -> default" /> - + <!-- For manual testing with PostgreSQL (see SQLTestConstants) --> - <!-- - <dependency org="postgresql" name="postgresql" - rev="9.1-901.jdbc3" conf="test,ide->default" /> - --> + <!-- <dependency org="postgresql" name="postgresql" rev="9.1-901.jdbc3" + conf="test,ide->default" /> --> </dependencies> diff --git a/server/src/com/vaadin/annotations/Push.java b/server/src/com/vaadin/annotations/Push.java index 58e70acf21..d5e42d6f60 100644 --- a/server/src/com/vaadin/annotations/Push.java +++ b/server/src/com/vaadin/annotations/Push.java @@ -22,6 +22,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.vaadin.shared.communication.PushMode; +import com.vaadin.shared.ui.ui.Transport; import com.vaadin.ui.UI; /** @@ -46,4 +47,13 @@ public @interface Push { */ public PushMode value() default PushMode.AUTOMATIC; + /** + * Returns the transport type used for the push for the annotated UI. The + * default transport type when this annotation is present is + * {@link Transport#WEBSOCKET}. + * + * @return the transport type to use + */ + public Transport transport() default Transport.DEFAULT; + } diff --git a/server/src/com/vaadin/annotations/VaadinServletConfiguration.java b/server/src/com/vaadin/annotations/VaadinServletConfiguration.java new file mode 100644 index 0000000000..38e3ff2ef0 --- /dev/null +++ b/server/src/com/vaadin/annotations/VaadinServletConfiguration.java @@ -0,0 +1,143 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import com.vaadin.server.Constants; +import com.vaadin.server.DefaultDeploymentConfiguration; +import com.vaadin.server.DeploymentConfiguration; +import com.vaadin.server.DeploymentConfiguration.LegacyProperyToStringMode; +import com.vaadin.server.VaadinServlet; +import com.vaadin.server.VaadinSession; +import com.vaadin.ui.UI; + +/** + * Annotation for configuring subclasses of {@link VaadinServlet}. For a + * {@link VaadinServlet} class that has this annotation, the defined values are + * read during initialization and will be available using + * {@link DeploymentConfiguration#getApplicationOrSystemProperty(String, String)} + * as well as from specific methods in {@link DeploymentConfiguration}. Init + * params defined in <code>web.xml</code> or the <code>@WebServlet</code> + * annotation take precedence over values defined in this annotation. + * + * @since 7.1 + * @author Vaadin Ltd + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface VaadinServletConfiguration { + /** + * Defines the init parameter name for methods in + * {@link VaadinServletConfiguration}. + * + * @since 7.1 + * @author Vaadin Ltd + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + @Documented + public @interface InitParameterName { + /** + * The name of the init parameter that the annotated method controls. + * + * @return the parameter name + */ + public String value(); + } + + /** + * Whether Vaadin is in production mode. + * + * @return true if in production mode, false otherwise. + * + * @see DeploymentConfiguration#isProductionMode() + */ + @InitParameterName(Constants.SERVLET_PARAMETER_PRODUCTION_MODE) + public boolean productionMode(); + + /** + * Gets the default UI class to use for the servlet. + * + * @return the default UI class + */ + @InitParameterName(VaadinSession.UI_PARAMETER) + public Class<? extends UI> ui(); + + /** + * The time resources can be cached in the browser, in seconds. The default + * value is + * {@value DefaultDeploymentConfiguration#DEFAULT_RESOURCE_CACHE_TIME}. + * + * @return the resource cache time + * + * @see DeploymentConfiguration#getResourceCacheTime() + */ + @InitParameterName(Constants.SERVLET_PARAMETER_RESOURCE_CACHE_TIME) + public int resourceCacheTime() default DefaultDeploymentConfiguration.DEFAULT_RESOURCE_CACHE_TIME; + + /** + * The number of seconds between heartbeat requests of a UI, or a + * non-positive number if heartbeat is disabled. The default value is + * {@value DefaultDeploymentConfiguration#DEFAULT_HEARTBEAT_INTERVAL}. + * + * @return the time between heartbeats + * + * @see DeploymentConfiguration#getHeartbeatInterval() + */ + @InitParameterName(Constants.SERVLET_PARAMETER_HEARTBEAT_INTERVAL) + public int heartbeatInterval() default DefaultDeploymentConfiguration.DEFAULT_HEARTBEAT_INTERVAL; + + /** + * Whether a session should be closed when all its open UIs have been idle + * for longer than its configured maximum inactivity time. The default value + * is {@value DefaultDeploymentConfiguration#DEFAULT_CLOSE_IDLE_SESSIONS}. + * + * @return true if UIs and sessions receiving only heartbeat requests are + * eventually closed; false if heartbeat requests extend UI and + * session lifetime indefinitely + * + * @see DeploymentConfiguration#isCloseIdleSessions() + */ + @InitParameterName(Constants.SERVLET_PARAMETER_CLOSE_IDLE_SESSIONS) + public boolean closeIdleSessions() default DefaultDeploymentConfiguration.DEFAULT_CLOSE_IDLE_SESSIONS; + + /** + * The default widgetset to use for the servlet. The default value is + * {@value VaadinServlet#DEFAULT_WIDGETSET}. + * + * @return the default widgetset name + */ + @InitParameterName(VaadinServlet.PARAMETER_WIDGETSET) + public String widgetset() default VaadinServlet.DEFAULT_WIDGETSET; + + /** + * The legacy Property.toString() mode used. The default value is + * {@link LegacyProperyToStringMode#DISABLED} + * + * @return The Property.toString() mode in use. + * + * @deprecated as of 7.1, should only be used to ease migration + */ + @Deprecated + @InitParameterName(Constants.SERVLET_PARAMETER_LEGACY_PROPERTY_TOSTRING) + public LegacyProperyToStringMode legacyPropertyToStringMode() default LegacyProperyToStringMode.DISABLED; +} diff --git a/server/src/com/vaadin/data/util/LegacyPropertyHelper.java b/server/src/com/vaadin/data/util/LegacyPropertyHelper.java index 0276e35dbf..76bd57117d 100644 --- a/server/src/com/vaadin/data/util/LegacyPropertyHelper.java +++ b/server/src/com/vaadin/data/util/LegacyPropertyHelper.java @@ -15,6 +15,7 @@ */ package com.vaadin.data.util; +import java.io.Serializable; import java.util.logging.Level; import java.util.logging.Logger; @@ -32,7 +33,7 @@ import com.vaadin.server.VaadinService; * @deprecated This is only used internally for backwards compatibility */ @Deprecated -public class LegacyPropertyHelper { +public class LegacyPropertyHelper implements Serializable { /** * Returns the property value converted to a String. @@ -59,6 +60,11 @@ public class LegacyPropertyHelper { getLogger().log(Level.WARNING, Constants.WARNING_LEGACY_PROPERTY_TOSTRING, p.getClass().getName()); + if (getLogger().isLoggable(Level.FINE)) { + getLogger().log(Level.FINE, + "Strack trace for legacy toString to ease debugging", + new Throwable()); + } } /** @@ -76,8 +82,8 @@ public class LegacyPropertyHelper { */ public static boolean isLegacyToStringEnabled() { if (VaadinService.getCurrent() == null) { - // This should really not happen but we need to handle it somehow. - // IF it happens it seems more safe to use the legacy mode and log. + // This will happen at least in JUnit tests. We do not what the real + // value should be but it seems more safe to use the legacy mode. return true; } return VaadinService.getCurrent().getDeploymentConfiguration() @@ -86,9 +92,9 @@ public class LegacyPropertyHelper { private static boolean logLegacyToStringWarning() { if (VaadinService.getCurrent() == null) { - // This should really not happen but we need to handle it somehow. - // IF it happens it seems more safe to use the legacy mode and log. - return true; + // This will happen at least in JUnit tests. We do not want to spam + // the log with these messages in this case. + return false; } return VaadinService.getCurrent().getDeploymentConfiguration() .getLegacyPropertyToStringMode() == LegacyProperyToStringMode.WARNING; diff --git a/server/src/com/vaadin/data/util/converter/AbstractStringToNumberConverter.java b/server/src/com/vaadin/data/util/converter/AbstractStringToNumberConverter.java new file mode 100644 index 0000000000..5999d850b4 --- /dev/null +++ b/server/src/com/vaadin/data/util/converter/AbstractStringToNumberConverter.java @@ -0,0 +1,120 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.data.util.converter; + +import java.text.NumberFormat; +import java.text.ParsePosition; +import java.util.Locale; + +/** + * A converter that converts from the number type T to {@link String} and back. + * Uses the given locale and {@link NumberFormat} for formatting and parsing. + * Automatically trims the input string, removing any leading and trailing white + * space. + * <p> + * Override and overwrite {@link #getFormat(Locale)} to use a different format. + * </p> + * + * @author Vaadin Ltd + * @since 7.1 + */ +public abstract class AbstractStringToNumberConverter<T> implements + Converter<String, T> { + + /** + * Returns the format used by {@link #convertToPresentation(Object, Locale)} + * and {@link #convertToModel(Object, Locale)}. + * + * @param locale + * The locale to use + * @return A NumberFormat instance + * @since 7.1 + */ + protected NumberFormat getFormat(Locale locale) { + if (locale == null) { + locale = Locale.getDefault(); + } + + return NumberFormat.getNumberInstance(locale); + } + + /** + * Convert the value to a Number using the given locale and + * {@link #getFormat(Locale)}. + * + * @param value + * The value to convert + * @param locale + * The locale to use for conversion + * @return The converted value + * @throws ConversionException + * If there was a problem converting the value + * @since 7.1 + */ + protected Number convertToNumber(String value, Locale locale) + throws ConversionException { + if (value == null) { + return null; + } + + // Remove leading and trailing white space + value = value.trim(); + + // Parse and detect errors. If the full string was not used, it is + // an error. + ParsePosition parsePosition = new ParsePosition(0); + Number parsedValue = getFormat(locale).parse(value, parsePosition); + if (parsePosition.getIndex() != value.length()) { + throw new ConversionException("Could not convert '" + value + + "' to " + getModelType().getName()); + } + + if (parsedValue == null) { + // Convert "" to null + return null; + } + return parsedValue; + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang + * .Object, java.util.Locale) + */ + @Override + public String convertToPresentation(T value, Locale locale) + throws ConversionException { + if (value == null) { + return null; + } + + return getFormat(locale).format(value); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.util.converter.Converter#getPresentationType() + */ + @Override + public Class<String> getPresentationType() { + return String.class; + } + +} diff --git a/server/src/com/vaadin/data/util/converter/Converter.java b/server/src/com/vaadin/data/util/converter/Converter.java index be9bb32413..ded7da7fb5 100644 --- a/server/src/com/vaadin/data/util/converter/Converter.java +++ b/server/src/com/vaadin/data/util/converter/Converter.java @@ -38,12 +38,12 @@ import java.util.Locale; * If conversion of a value fails, a {@link ConversionException} is thrown. * </p> * - * @param <MODEL> - * The model type. Must be compatible with what - * {@link #getModelType()} returns. * @param <PRESENTATION> * The presentation type. Must be compatible with what * {@link #getPresentationType()} returns. + * @param <MODEL> + * The model type. Must be compatible with what + * {@link #getModelType()} returns. * @author Vaadin Ltd. * @since 7.0 */ diff --git a/server/src/com/vaadin/data/util/converter/ConverterUtil.java b/server/src/com/vaadin/data/util/converter/ConverterUtil.java index 61d155bc9a..08d7363084 100644 --- a/server/src/com/vaadin/data/util/converter/ConverterUtil.java +++ b/server/src/com/vaadin/data/util/converter/ConverterUtil.java @@ -151,10 +151,14 @@ public class ConverterUtil implements Serializable { /** * Checks if the given converter can handle conversion between the given - * presentation and model type + * presentation and model type. Does strict type checking and only returns + * true if the converter claims it can handle exactly the given types. + * + * @see #canConverterPossiblyHandle(Converter, Class, Class) * * @param converter - * The converter to check + * The converter to check. If this is null the result is always + * false. * @param presentationType * The presentation type * @param modelType @@ -168,10 +172,48 @@ public class ConverterUtil implements Serializable { return false; } - if (!modelType.isAssignableFrom(converter.getModelType())) { + if (modelType != converter.getModelType()) { + return false; + } + if (presentationType != converter.getPresentationType()) { return false; } - if (!presentationType.isAssignableFrom(converter.getPresentationType())) { + + return true; + } + + /** + * Checks if it possible that the given converter can handle conversion + * between the given presentation and model type somehow. + * + * @param converter + * The converter to check. If this is null the result is always + * false. + * @param presentationType + * The presentation type + * @param modelType + * The model type + * @return true if the converter possibly support conversion between the + * given presentation and model type, false otherwise + */ + public static boolean canConverterPossiblyHandle(Converter<?, ?> converter, + Class<?> presentationType, Class<?> modelType) { + if (converter == null) { + return false; + } + Class<?> converterModelType = converter.getModelType(); + + if (!modelType.isAssignableFrom(converterModelType) + && !converterModelType.isAssignableFrom(modelType)) { + // model types are not compatible in any way + return false; + } + + Class<?> converterPresentationType = converter.getPresentationType(); + if (!presentationType.isAssignableFrom(converterPresentationType) + && !converterPresentationType + .isAssignableFrom(presentationType)) { + // presentation types are not compatible in any way return false; } diff --git a/server/src/com/vaadin/data/util/converter/DateToSqlDateConverter.java b/server/src/com/vaadin/data/util/converter/DateToSqlDateConverter.java new file mode 100644 index 0000000000..97027cc05b --- /dev/null +++ b/server/src/com/vaadin/data/util/converter/DateToSqlDateConverter.java @@ -0,0 +1,59 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +/** + * + */ +package com.vaadin.data.util.converter; + +import java.util.Date; +import java.util.Locale; + +/** + * Converter for handling conversion between {@link java.util.Date} and + * {@link java.sql.Date}. This is used when a PopupDateField or InlineDateField + * is connected to a java.sql.Date property, typically through a JPAContainer or + * SQLContainer. Note that information (time information) is lost when + * converting from {@link java.util.Date} to {@link java.sql.Date}. + * + * @since 7.1 + * @author Vaadin Ltd + */ +public class DateToSqlDateConverter implements Converter<Date, java.sql.Date> { + + @Override + public java.sql.Date convertToModel(Date value, Locale locale) + throws ConversionException { + return new java.sql.Date(value.getTime()); + } + + @Override + public Date convertToPresentation(java.sql.Date value, Locale locale) + throws ConversionException { + return new Date(value.getTime()); + } + + @Override + public Class<java.sql.Date> getModelType() { + return java.sql.Date.class; + } + + @Override + public Class<Date> getPresentationType() { + return Date.class; + } + +} diff --git a/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java b/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java index de183dd342..bbd3945a37 100644 --- a/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java +++ b/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java @@ -87,6 +87,8 @@ public class DefaultConverterFactory implements ConverterFactory { protected Converter<Date, ?> createDateConverter(Class<?> sourceType) { if (Long.class.isAssignableFrom(sourceType)) { return new DateToLongConverter(); + } else if (java.sql.Date.class.isAssignableFrom(sourceType)) { + return new DateToSqlDateConverter(); } else { return null; } diff --git a/server/src/com/vaadin/data/util/converter/StringToDoubleConverter.java b/server/src/com/vaadin/data/util/converter/StringToDoubleConverter.java index 69a0faf8f4..8bb82498b9 100644 --- a/server/src/com/vaadin/data/util/converter/StringToDoubleConverter.java +++ b/server/src/com/vaadin/data/util/converter/StringToDoubleConverter.java @@ -17,7 +17,6 @@ package com.vaadin.data.util.converter; import java.text.NumberFormat; -import java.text.ParsePosition; import java.util.Locale; /** @@ -34,23 +33,8 @@ import java.util.Locale; * @author Vaadin Ltd * @since 7.0 */ -public class StringToDoubleConverter implements Converter<String, Double> { - - /** - * Returns the format used by {@link #convertToPresentation(Double, Locale)} - * and {@link #convertToModel(String, Locale)}. - * - * @param locale - * The locale to use - * @return A NumberFormat instance - */ - protected NumberFormat getFormat(Locale locale) { - if (locale == null) { - locale = Locale.getDefault(); - } - - return NumberFormat.getNumberInstance(locale); - } +public class StringToDoubleConverter extends + AbstractStringToNumberConverter<Double> { /* * (non-Javadoc) @@ -62,42 +46,8 @@ public class StringToDoubleConverter implements Converter<String, Double> { @Override public Double convertToModel(String value, Locale locale) throws ConversionException { - if (value == null) { - return null; - } - - // Remove leading and trailing white space - value = value.trim(); - - ParsePosition parsePosition = new ParsePosition(0); - Number parsedValue = getFormat(locale).parse(value, parsePosition); - if (parsePosition.getIndex() != value.length()) { - throw new ConversionException("Could not convert '" + value - + "' to " + getModelType().getName()); - } - if (parsedValue == null) { - // Convert "" to null - return null; - } - - return parsedValue.doubleValue(); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang - * .Object, java.util.Locale) - */ - @Override - public String convertToPresentation(Double value, Locale locale) - throws ConversionException { - if (value == null) { - return null; - } - - return getFormat(locale).format(value); + Number n = convertToNumber(value, locale); + return n == null ? null : n.doubleValue(); } /* @@ -110,13 +60,4 @@ public class StringToDoubleConverter implements Converter<String, Double> { return Double.class; } - /* - * (non-Javadoc) - * - * @see com.vaadin.data.util.converter.Converter#getPresentationType() - */ - @Override - public Class<String> getPresentationType() { - return String.class; - } } diff --git a/server/src/com/vaadin/data/util/converter/StringToFloatConverter.java b/server/src/com/vaadin/data/util/converter/StringToFloatConverter.java index 1adfd87565..a207654358 100644 --- a/server/src/com/vaadin/data/util/converter/StringToFloatConverter.java +++ b/server/src/com/vaadin/data/util/converter/StringToFloatConverter.java @@ -17,7 +17,6 @@ package com.vaadin.data.util.converter; import java.text.NumberFormat; -import java.text.ParsePosition; import java.util.Locale; /** @@ -34,23 +33,8 @@ import java.util.Locale; * @author Vaadin Ltd * @since 7.0 */ -public class StringToFloatConverter implements Converter<String, Float> { - - /** - * Returns the format used by {@link #convertToPresentation(Float, Locale)} - * and {@link #convertToModel(String, Locale)}. - * - * @param locale - * The locale to use - * @return A NumberFormat instance - */ - protected NumberFormat getFormat(Locale locale) { - if (locale == null) { - locale = Locale.getDefault(); - } - - return NumberFormat.getNumberInstance(locale); - } +public class StringToFloatConverter extends + AbstractStringToNumberConverter<Float> { /* * (non-Javadoc) @@ -62,42 +46,8 @@ public class StringToFloatConverter implements Converter<String, Float> { @Override public Float convertToModel(String value, Locale locale) throws ConversionException { - if (value == null) { - return null; - } - - // Remove leading and trailing white space - value = value.trim(); - - ParsePosition parsePosition = new ParsePosition(0); - Number parsedValue = getFormat(locale).parse(value, parsePosition); - if (parsePosition.getIndex() != value.length()) { - throw new ConversionException("Could not convert '" + value - + "' to " + getModelType().getName()); - } - if (parsedValue == null) { - // Convert "" to null - return null; - } - - return parsedValue.floatValue(); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang - * .Object, java.util.Locale) - */ - @Override - public String convertToPresentation(Float value, Locale locale) - throws ConversionException { - if (value == null) { - return null; - } - - return getFormat(locale).format(value); + Number n = convertToNumber(value, locale); + return n == null ? null : n.floatValue(); } /* @@ -110,13 +60,4 @@ public class StringToFloatConverter implements Converter<String, Float> { return Float.class; } - /* - * (non-Javadoc) - * - * @see com.vaadin.data.util.converter.Converter#getPresentationType() - */ - @Override - public Class<String> getPresentationType() { - return String.class; - } } diff --git a/server/src/com/vaadin/data/util/converter/StringToIntegerConverter.java b/server/src/com/vaadin/data/util/converter/StringToIntegerConverter.java index 4bb933bcc8..4f34cf1cd3 100644 --- a/server/src/com/vaadin/data/util/converter/StringToIntegerConverter.java +++ b/server/src/com/vaadin/data/util/converter/StringToIntegerConverter.java @@ -17,7 +17,6 @@ package com.vaadin.data.util.converter; import java.text.NumberFormat; -import java.text.ParsePosition; import java.util.Locale; /** @@ -31,7 +30,8 @@ import java.util.Locale; * @author Vaadin Ltd * @since 7.0 */ -public class StringToIntegerConverter implements Converter<String, Integer> { +public class StringToIntegerConverter extends + AbstractStringToNumberConverter<Integer> { /** * Returns the format used by @@ -42,6 +42,7 @@ public class StringToIntegerConverter implements Converter<String, Integer> { * The locale to use * @return A NumberFormat instance */ + @Override protected NumberFormat getFormat(Locale locale) { if (locale == null) { locale = Locale.getDefault(); @@ -49,50 +50,29 @@ public class StringToIntegerConverter implements Converter<String, Integer> { return NumberFormat.getIntegerInstance(locale); } + /* + * (non-Javadoc) + * + * @see + * com.vaadin.data.util.converter.Converter#convertToModel(java.lang.Object, + * java.util.Locale) + */ @Override public Integer convertToModel(String value, Locale locale) throws ConversionException { - if (value == null) { - return null; - } - - // Remove leading and trailing white space - value = value.trim(); + Number n = convertToNumber(value, locale); + return n == null ? null : n.intValue(); - // Parse and detect errors. If the full string was not used, it is - // an error. - ParsePosition parsePosition = new ParsePosition(0); - Number parsedValue = getFormat(locale).parse(value, parsePosition); - if (parsePosition.getIndex() != value.length()) { - throw new ConversionException("Could not convert '" + value - + "' to " + getModelType().getName()); - } - - if (parsedValue == null) { - // Convert "" to null - return null; - } - return parsedValue.intValue(); - } - - @Override - public String convertToPresentation(Integer value, Locale locale) - throws ConversionException { - if (value == null) { - return null; - } - - return getFormat(locale).format(value); } + /* + * (non-Javadoc) + * + * @see com.vaadin.data.util.converter.Converter#getModelType() + */ @Override public Class<Integer> getModelType() { return Integer.class; } - @Override - public Class<String> getPresentationType() { - return String.class; - } - } diff --git a/server/src/com/vaadin/data/util/converter/StringToNumberConverter.java b/server/src/com/vaadin/data/util/converter/StringToNumberConverter.java index 99ff7007ad..eae73e4cfa 100644 --- a/server/src/com/vaadin/data/util/converter/StringToNumberConverter.java +++ b/server/src/com/vaadin/data/util/converter/StringToNumberConverter.java @@ -17,7 +17,6 @@ package com.vaadin.data.util.converter; import java.text.NumberFormat; -import java.text.ParsePosition; import java.util.Locale; /** @@ -30,23 +29,8 @@ import java.util.Locale; * @author Vaadin Ltd * @since 7.0 */ -public class StringToNumberConverter implements Converter<String, Number> { - - /** - * Returns the format used by {@link #convertToPresentation(Number, Locale)} - * and {@link #convertToModel(String, Locale)}. - * - * @param locale - * The locale to use - * @return A NumberFormat instance - */ - protected NumberFormat getFormat(Locale locale) { - if (locale == null) { - locale = Locale.getDefault(); - } - - return NumberFormat.getNumberInstance(locale); - } +public class StringToNumberConverter extends + AbstractStringToNumberConverter<Number> { /* * (non-Javadoc) @@ -58,44 +42,7 @@ public class StringToNumberConverter implements Converter<String, Number> { @Override public Number convertToModel(String value, Locale locale) throws ConversionException { - if (value == null) { - return null; - } - - // Remove leading and trailing white space - value = value.trim(); - - // Parse and detect errors. If the full string was not used, it is - // an error. - ParsePosition parsePosition = new ParsePosition(0); - Number parsedValue = getFormat(locale).parse(value, parsePosition); - if (parsePosition.getIndex() != value.length()) { - throw new ConversionException("Could not convert '" + value - + "' to " + getModelType().getName()); - } - - if (parsedValue == null) { - // Convert "" to null - return null; - } - return parsedValue; - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang - * .Object, java.util.Locale) - */ - @Override - public String convertToPresentation(Number value, Locale locale) - throws ConversionException { - if (value == null) { - return null; - } - - return getFormat(locale).format(value); + return convertToNumber(value, locale); } /* @@ -108,14 +55,4 @@ public class StringToNumberConverter implements Converter<String, Number> { return Number.class; } - /* - * (non-Javadoc) - * - * @see com.vaadin.data.util.converter.Converter#getPresentationType() - */ - @Override - public Class<String> getPresentationType() { - return String.class; - } - } diff --git a/server/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java b/server/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java index 65c1050fb0..0cc2f0a1a5 100644 --- a/server/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java +++ b/server/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java @@ -48,7 +48,7 @@ public class SourceIs extends ClientSideCriterion { int paintedComponents = 0; for (int i = 0; i < components.length; i++) { Component c = components[i]; - if (c.getUI() != null && c.getUI().getSession() != null) { + if (c.isAttached()) { target.addAttribute("component" + paintedComponents++, c); } else { Logger.getLogger(SourceIs.class.getName()) diff --git a/server/src/com/vaadin/navigator/Navigator.java b/server/src/com/vaadin/navigator/Navigator.java index df05a9fbce..540a3ee302 100644 --- a/server/src/com/vaadin/navigator/Navigator.java +++ b/server/src/com/vaadin/navigator/Navigator.java @@ -497,19 +497,22 @@ public class Navigator implements Serializable { */ public void navigateTo(String navigationState) { String longestViewName = null; + ViewProvider longestViewNameProvider = null; View viewWithLongestName = null; for (ViewProvider provider : providers) { String viewName = provider.getViewName(navigationState); if (null != viewName && (longestViewName == null || viewName.length() > longestViewName .length())) { - View view = provider.getView(viewName); - if (null != view) { - longestViewName = viewName; - viewWithLongestName = view; - } + longestViewName = viewName; + longestViewNameProvider = provider; } } + if (longestViewName != null) { + viewWithLongestName = longestViewNameProvider + .getView(longestViewName); + } + if (viewWithLongestName == null && errorProvider != null) { longestViewName = errorProvider.getViewName(navigationState); viewWithLongestName = errorProvider.getView(longestViewName); diff --git a/server/src/com/vaadin/server/AbstractClientConnector.java b/server/src/com/vaadin/server/AbstractClientConnector.java index e998b8ed55..01f7d9af42 100644 --- a/server/src/com/vaadin/server/AbstractClientConnector.java +++ b/server/src/com/vaadin/server/AbstractClientConnector.java @@ -577,7 +577,7 @@ public abstract class AbstractClientConnector implements ClientConnector, } // Send detach event if the component have been connected to a window - if (getSession() != null) { + if (isAttached()) { detach(); } @@ -585,7 +585,7 @@ public abstract class AbstractClientConnector implements ClientConnector, this.parent = parent; // Send attach event if connected to an application - if (getSession() != null) { + if (isAttached()) { attach(); } } @@ -595,6 +595,16 @@ public abstract class AbstractClientConnector implements ClientConnector, return parent; } + /* + * (non-Javadoc) + * + * @see com.vaadin.server.ClientConnector#isAttached() + */ + @Override + public boolean isAttached() { + return getSession() != null; + } + @Override public void attach() { markAsDirty(); diff --git a/server/src/com/vaadin/server/ClientConnector.java b/server/src/com/vaadin/server/ClientConnector.java index 3b52fbc730..9e328bb6ef 100644 --- a/server/src/com/vaadin/server/ClientConnector.java +++ b/server/src/com/vaadin/server/ClientConnector.java @@ -226,14 +226,22 @@ public interface ClientConnector extends Connector { public void setParent(ClientConnector parent); /** - * Notifies the connector that it is connected to an application. + * Checks if the connector is attached to a VaadinSession. * + * @since 7.1 + * @return true if the connector is attached to a session, false otherwise + */ + public boolean isAttached(); + + /** + * Notifies the connector that it is connected to a VaadinSession (and + * therefore also to a UI). * <p> * The caller of this method is {@link #setParent(ClientConnector)} if the - * parent is itself already attached to the application. If not, the parent - * will call the {@link #attach()} for all its children when it is attached - * to the application. This method is always called before the connector's - * data is sent to the client-side for the first time. + * parent is itself already attached to the session. If not, the parent will + * call the {@link #attach()} for all its children when it is attached to + * the session. This method is always called before the connector's data is + * sent to the client-side for the first time. * </p> * * <p> @@ -243,13 +251,13 @@ public interface ClientConnector extends Connector { public void attach(); /** - * Notifies the connector that it is detached from the application. + * Notifies the connector that it is detached from its VaadinSession. * * <p> * The caller of this method is {@link #setParent(ClientConnector)} if the - * parent is in the application. When the parent is detached from the - * application it is its responsibility to call {@link #detach()} for each - * of its children. + * parent is in the session. When the parent is detached from the session it + * is its responsibility to call {@link #detach()} for each of its children. + * * </p> */ public void detach(); diff --git a/server/src/com/vaadin/server/ComponentSizeValidator.java b/server/src/com/vaadin/server/ComponentSizeValidator.java index 27d087a2b2..07c195a1c1 100644 --- a/server/src/com/vaadin/server/ComponentSizeValidator.java +++ b/server/src/com/vaadin/server/ComponentSizeValidator.java @@ -16,8 +16,8 @@ package com.vaadin.server; import java.io.PrintStream; -import java.io.PrintWriter; import java.io.Serializable; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; @@ -40,6 +40,7 @@ import com.vaadin.ui.GridLayout.Area; import com.vaadin.ui.Layout; import com.vaadin.ui.Panel; import com.vaadin.ui.TabSheet; +import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; @@ -190,14 +191,14 @@ public class ComponentSizeValidator implements Serializable { subErrors.add(error); } - public void reportErrors(PrintWriter clientJSON, + public void reportErrors(StringBuilder clientJSON, PrintStream serverErrorStream) { - clientJSON.write("{"); + clientJSON.append("{"); Component parent = component.getParent(); String paintableId = component.getConnectorId(); - clientJSON.print("id:\"" + paintableId + "\""); + clientJSON.append("\"id\":\"" + paintableId + "\""); if (invalidHeight) { Stack<ComponentInfo> attributes = null; @@ -227,7 +228,7 @@ public class ComponentSizeValidator implements Serializable { attributes = getHeightAttributes(component); } printServerError(msg, attributes, false, serverErrorStream); - clientJSON.print(",\"heightMsg\":\"" + msg + "\""); + clientJSON.append(",\"heightMsg\":\"" + msg + "\""); } if (invalidWidth) { Stack<ComponentInfo> attributes = null; @@ -255,25 +256,25 @@ public class ComponentSizeValidator implements Serializable { msg = "A component with relative width needs a parent with defined width."; attributes = getWidthAttributes(component); } - clientJSON.print(",\"widthMsg\":\"" + msg + "\""); + clientJSON.append(",\"widthMsg\":\"" + msg + "\""); printServerError(msg, attributes, true, serverErrorStream); } if (subErrors.size() > 0) { serverErrorStream.println("Sub errors >>"); - clientJSON.write(", \"subErrors\" : ["); + clientJSON.append(", \"subErrors\" : ["); boolean first = true; for (InvalidLayout subError : subErrors) { if (!first) { - clientJSON.print(","); + clientJSON.append(","); } else { first = false; } subError.reportErrors(clientJSON, serverErrorStream); } - clientJSON.write("]"); + clientJSON.append("]"); serverErrorStream.println("<< Sub erros"); } - clientJSON.write("}"); + clientJSON.append("}"); } } @@ -673,4 +674,31 @@ public class ComponentSizeValidator implements Serializable { return Logger.getLogger(ComponentSizeValidator.class.getName()); } + /** + * Validates the layout and returns a collection of errors + * + * @since 7.1 + * @param ui + * The UI to validate + * @return A collection of errors. An empty collection if there are no + * errors. + */ + public static List<InvalidLayout> validateLayouts(UI ui) { + List<InvalidLayout> invalidRelativeSizes = ComponentSizeValidator + .validateComponentRelativeSizes(ui.getContent(), + new ArrayList<ComponentSizeValidator.InvalidLayout>(), + null); + + // Also check any existing subwindows + if (ui.getWindows() != null) { + for (Window subWindow : ui.getWindows()) { + invalidRelativeSizes = ComponentSizeValidator + .validateComponentRelativeSizes(subWindow.getContent(), + invalidRelativeSizes, null); + } + } + return invalidRelativeSizes; + + } + } diff --git a/server/src/com/vaadin/server/ConnectorResourceHandler.java b/server/src/com/vaadin/server/ConnectorResourceHandler.java index 00d82988d3..3f3f41a179 100644 --- a/server/src/com/vaadin/server/ConnectorResourceHandler.java +++ b/server/src/com/vaadin/server/ConnectorResourceHandler.java @@ -77,8 +77,8 @@ public class ConnectorResourceHandler implements RequestHandler { session.unlock(); } - Map<Class<?>, CurrentInstance> oldThreadLocals = CurrentInstance - .setThreadLocals(ui); + Map<Class<?>, CurrentInstance> oldInstances = CurrentInstance + .setCurrent(ui); try { if (!connector.handleConnectorRequest(request, response, key)) { return error(request, response, connector.getClass() @@ -88,7 +88,7 @@ public class ConnectorResourceHandler implements RequestHandler { + ") did not handle connector request for " + key); } } finally { - CurrentInstance.restoreThreadLocals(oldThreadLocals); + CurrentInstance.restoreInstances(oldInstances); } return true; diff --git a/server/src/com/vaadin/server/Constants.java b/server/src/com/vaadin/server/Constants.java index f8d8105286..2c041e3cf8 100644 --- a/server/src/com/vaadin/server/Constants.java +++ b/server/src/com/vaadin/server/Constants.java @@ -65,11 +65,11 @@ public interface Constants { + " Widgetset version: %s\n" + "================================================================="; - static final String REQUIRED_ATMOSPHERE_VERSION = "1.0.12"; + static final String REQUIRED_ATMOSPHERE_VERSION = "1.0.13"; static final String INVALID_ATMOSPHERE_VERSION_WARNING = "\n" + "=================================================================\n" - + "Vaadin depends on Atomsphere {0} but version {1} was found.\n" + + "Vaadin depends on Atmosphere {0} but version {1} was found.\n" + "This might cause compatibility problems if push is used.\n" + "================================================================="; @@ -106,7 +106,8 @@ public interface Constants { + "\" to \"true\". To disable the legacy functionality, set \"" + Constants.SERVLET_PARAMETER_LEGACY_PROPERTY_TOSTRING + "\" to false." - + " (Note that your debugger might call toString() and trigger this message)."; + + " (Note that your debugger might call toString() and trigger this message)." + + " To find out who is calling toString(), enable FINE level logging."; static final String WARNING_UNKNOWN_LEGACY_PROPERTY_TOSTRING_VALUE = "Unknown value '{0}' for parameter " + Constants.SERVLET_PARAMETER_LEGACY_PROPERTY_TOSTRING diff --git a/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java b/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java index 80c3644d77..a55c3231f3 100644 --- a/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java +++ b/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java @@ -30,6 +30,27 @@ import com.vaadin.shared.communication.PushMode; * @since 7.0.0 */ public class DefaultDeploymentConfiguration implements DeploymentConfiguration { + /** + * Default value for {@link #getResourceCacheTime()} = {@value} . + */ + public static final int DEFAULT_RESOURCE_CACHE_TIME = 3600; + + /** + * Default value for {@link #getHeartbeatInterval()} = {@value} . + */ + public static final int DEFAULT_HEARTBEAT_INTERVAL = 300; + + /** + * Default value for {@link #isCloseIdleSessions()} = {@value} . + */ + public static final boolean DEFAULT_CLOSE_IDLE_SESSIONS = false; + + /** + * Default value for {@link #getLegacyPropertyToStringMode()} = + * {@link LegacyProperyToStringMode#WARNING}. + */ + public static final LegacyProperyToStringMode DEFAULT_LEGACY_PROPERTY_TO_STRING = LegacyProperyToStringMode.WARNING; + private final Properties initParameters; private boolean productionMode; private boolean xsrfProtectionEnabled; @@ -66,20 +87,17 @@ public class DefaultDeploymentConfiguration implements DeploymentConfiguration { private void checkLegacyPropertyToString() { String param = getApplicationOrSystemProperty( - Constants.SERVLET_PARAMETER_LEGACY_PROPERTY_TOSTRING, "warning"); - if ("true".equals(param)) { - legacyPropertyToStringMode = LegacyProperyToStringMode.ENABLED; - } else if ("false".equals(param)) { - legacyPropertyToStringMode = LegacyProperyToStringMode.DISABLED; - } else { - if (!"warning".equals(param)) { - getLogger() - .log(Level.WARNING, - Constants.WARNING_UNKNOWN_LEGACY_PROPERTY_TOSTRING_VALUE, - param); - } - legacyPropertyToStringMode = LegacyProperyToStringMode.WARNING; + Constants.SERVLET_PARAMETER_LEGACY_PROPERTY_TOSTRING, + DEFAULT_LEGACY_PROPERTY_TO_STRING.name().toLowerCase()); + try { + legacyPropertyToStringMode = LegacyProperyToStringMode + .valueOf(param.toUpperCase()); + } catch (IllegalArgumentException e) { + getLogger().log(Level.WARNING, + Constants.WARNING_UNKNOWN_LEGACY_PROPERTY_TOSTRING_VALUE, + param); + legacyPropertyToStringMode = DEFAULT_LEGACY_PROPERTY_TO_STRING; } } @@ -250,11 +268,11 @@ public class DefaultDeploymentConfiguration implements DeploymentConfiguration { resourceCacheTime = Integer .parseInt(getApplicationOrSystemProperty( Constants.SERVLET_PARAMETER_RESOURCE_CACHE_TIME, - "3600")); + Integer.toString(DEFAULT_RESOURCE_CACHE_TIME))); } catch (NumberFormatException e) { getLogger().warning( Constants.WARNING_RESOURCE_CACHING_TIME_NOT_NUMERIC); - resourceCacheTime = 3600; + resourceCacheTime = DEFAULT_RESOURCE_CACHE_TIME; } } @@ -263,18 +281,18 @@ public class DefaultDeploymentConfiguration implements DeploymentConfiguration { heartbeatInterval = Integer .parseInt(getApplicationOrSystemProperty( Constants.SERVLET_PARAMETER_HEARTBEAT_INTERVAL, - "300")); + Integer.toString(DEFAULT_HEARTBEAT_INTERVAL))); } catch (NumberFormatException e) { getLogger().warning( Constants.WARNING_HEARTBEAT_INTERVAL_NOT_NUMERIC); - heartbeatInterval = 300; + heartbeatInterval = DEFAULT_HEARTBEAT_INTERVAL; } } private void checkCloseIdleSessions() { closeIdleSessions = getApplicationOrSystemProperty( - Constants.SERVLET_PARAMETER_CLOSE_IDLE_SESSIONS, "false") - .equals("true"); + Constants.SERVLET_PARAMETER_CLOSE_IDLE_SESSIONS, + Boolean.toString(DEFAULT_CLOSE_IDLE_SESSIONS)).equals("true"); } private void checkPushMode() { diff --git a/server/src/com/vaadin/server/DragAndDropService.java b/server/src/com/vaadin/server/DragAndDropService.java index a83e83ef7f..cc571853fe 100644 --- a/server/src/com/vaadin/server/DragAndDropService.java +++ b/server/src/com/vaadin/server/DragAndDropService.java @@ -375,4 +375,14 @@ public class DragAndDropService implements VariableOwner, ClientConnector { @Override public void removeDetachListener(DetachListener listener) { } + + /* + * (non-Javadoc) + * + * @see com.vaadin.server.ClientConnector#isAttached() + */ + @Override + public boolean isAttached() { + return true; + } } diff --git a/server/src/com/vaadin/server/GlobalResourceHandler.java b/server/src/com/vaadin/server/GlobalResourceHandler.java index d411b286d0..4235d85024 100644 --- a/server/src/com/vaadin/server/GlobalResourceHandler.java +++ b/server/src/com/vaadin/server/GlobalResourceHandler.java @@ -87,14 +87,14 @@ public class GlobalResourceHandler implements RequestHandler { + " is not a valid global resource path"); } session.lock(); - Map<Class<?>, CurrentInstance> oldThreadLocals = null; + Map<Class<?>, CurrentInstance> oldInstances = null; DownloadStream stream = null; try { UI ui = session.getUIById(Integer.parseInt(uiid)); if (ui == null) { return error(request, response, "No UI found for id " + uiid); } - oldThreadLocals = CurrentInstance.setThreadLocals(ui); + oldInstances = CurrentInstance.setCurrent(ui); ConnectorResource resource; if (LEGACY_TYPE.equals(type)) { resource = legacyResources.get(key); @@ -115,8 +115,8 @@ public class GlobalResourceHandler implements RequestHandler { } } finally { session.unlock(); - if (oldThreadLocals != null) { - CurrentInstance.restoreThreadLocals(oldThreadLocals); + if (oldInstances != null) { + CurrentInstance.restoreInstances(oldInstances); } } diff --git a/server/src/com/vaadin/server/JsonPaintTarget.java b/server/src/com/vaadin/server/JsonPaintTarget.java index ca70391f64..cd09b2a44b 100644 --- a/server/src/com/vaadin/server/JsonPaintTarget.java +++ b/server/src/com/vaadin/server/JsonPaintTarget.java @@ -388,10 +388,6 @@ public class JsonPaintTarget implements PaintTarget { getUsedResources().add("layouts/" + value + ".html"); } - if (name.equals("locale")) { - manager.requireLocale(value); - } - } @Override diff --git a/server/src/com/vaadin/server/LegacyApplication.java b/server/src/com/vaadin/server/LegacyApplication.java index 54550ce134..44649067c5 100644 --- a/server/src/com/vaadin/server/LegacyApplication.java +++ b/server/src/com/vaadin/server/LegacyApplication.java @@ -64,7 +64,7 @@ public abstract class LegacyApplication implements ErrorHandler { if (this.mainWindow != null) { throw new IllegalStateException("mainWindow has already been set"); } - if (mainWindow.getSession() != null) { + if (mainWindow.isAttached()) { throw new IllegalStateException( "mainWindow is attached to another application"); } diff --git a/server/src/com/vaadin/server/LegacyCommunicationManager.java b/server/src/com/vaadin/server/LegacyCommunicationManager.java index c0194db243..ad662cf6df 100644 --- a/server/src/com/vaadin/server/LegacyCommunicationManager.java +++ b/server/src/com/vaadin/server/LegacyCommunicationManager.java @@ -16,18 +16,12 @@ package com.vaadin.server; -import java.io.IOException; -import java.io.PrintWriter; import java.io.Serializable; -import java.io.Writer; import java.net.URI; import java.net.URISyntaxException; import java.security.GeneralSecurityException; -import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.logging.Level; @@ -37,7 +31,6 @@ import org.json.JSONException; import org.json.JSONObject; import com.vaadin.server.ClientConnector.ConnectorErrorEvent; -import com.vaadin.server.communication.LocaleWriter; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.JavaScriptConnectorState; import com.vaadin.shared.communication.SharedState; @@ -69,9 +62,6 @@ public class LegacyCommunicationManager implements Serializable { */ private final VaadinSession session; - // TODO Refactor to UI shared state (#11378) - private List<String> locales; - // TODO Move to VaadinSession (#11409) private DragAndDropService dragAndDropService; @@ -88,7 +78,6 @@ public class LegacyCommunicationManager implements Serializable { */ public LegacyCommunicationManager(VaadinSession session) { this.session = session; - requireLocale(session.getLocale().toString()); } protected VaadinSession getSession() { @@ -313,52 +302,6 @@ public class LegacyCommunicationManager implements Serializable { } /** - * Prints the queued (pending) locale definitions to a {@link PrintWriter} - * in a (UIDL) format that can be sent to the client and used there in - * formatting dates, times etc. - * - * @deprecated As of 7.1. See #11378. - * - * @param outWriter - */ - @Deprecated - public void printLocaleDeclarations(Writer writer) throws IOException { - new LocaleWriter().write(locales, writer); - } - - /** - * Queues a locale to be sent to the client (browser) for date and time - * entry etc. All locale specific information is derived from server-side - * {@link Locale} instances and sent to the client when needed, eliminating - * the need to use the {@link Locale} class and all the framework behind it - * on the client. - * - * @deprecated As of 7.1. See #11378. - * - * @see Locale#toString() - * - * @param value - */ - @Deprecated - public void requireLocale(String value) { - if (locales == null) { - locales = new ArrayList<String>(); - locales.add(session.getLocale().toString()); - } - if (!locales.contains(value)) { - locales.add(value); - } - } - - /** - * @deprecated As of 7.1. See #11378. - */ - @Deprecated - public void resetLocales() { - locales = null; - } - - /** * @deprecated As of 7.1. Will be removed in the future. */ @Deprecated @@ -486,10 +429,6 @@ public class LegacyCommunicationManager implements Serializable { getClientCache(ui).clear(); ui.getConnectorTracker().markAllConnectorsDirty(); ui.getConnectorTracker().markAllClientSidesUninitialized(); - - // Reset sent locales - resetLocales(); - requireLocale(session.getLocale().toString()); } private static final Logger getLogger() { diff --git a/server/src/com/vaadin/server/LocaleService.java b/server/src/com/vaadin/server/LocaleService.java new file mode 100644 index 0000000000..347c4da5c6 --- /dev/null +++ b/server/src/com/vaadin/server/LocaleService.java @@ -0,0 +1,211 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +/** + * + */ +package com.vaadin.server; + +import java.text.DateFormat; +import java.text.DateFormatSymbols; +import java.text.SimpleDateFormat; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.logging.Logger; + +import com.vaadin.shared.ui.ui.UIState.LocaleData; +import com.vaadin.shared.ui.ui.UIState.LocaleServiceState; +import com.vaadin.ui.UI; + +/** + * Server side service which handles locale and the transmission of locale date + * to the client side LocaleService. + * + * @since 7.1 + * @author Vaadin Ltd + */ +public class LocaleService { + + private UI ui; + + private LocaleServiceState state; + + /** + * Creates a LocaleService bound to the given UI + * + * @since 7.1 + * @param ui + * The UI which owns the LocaleService + */ + public LocaleService(UI ui, LocaleServiceState state) { + this.ui = ui; + this.state = state; + } + + /** + * Retrieves the UI this service is bound to + * + * @since 7.1 + * @return the UI for this service + */ + public UI getUI() { + return ui; + } + + /** + * Adds a locale to be sent to the client (browser) for date and time entry + * etc. All locale specific information is derived from server-side + * {@link Locale} instances and sent to the client when needed, eliminating + * the need to use the {@link Locale} class and all the framework behind it + * on the client. + * + * @param locale + * The locale which is required on the client side + */ + public void addLocale(Locale locale) { + for (LocaleData data : getState(false).localeData) { + if (data.name.equals(locale.toString())) { + // Already there + return; + } + } + + getState(true).localeData.add(createLocaleData(locale)); + } + + /** + * Returns the state for this service + * <p> + * The state is transmitted inside the UI state rather than as an individual + * entity. + * </p> + * + * @since 7.1 + * @param markAsDirty + * true to mark the state as dirty + * @return a LocaleServiceState object that can be read in any case and + * modified if markAsDirty is true + */ + private LocaleServiceState getState(boolean markAsDirty) { + if (markAsDirty) { + getUI().markAsDirty(); + } + + return state; + } + + /** + * Creates a LocaleData instance for transportation to the client + * + * @since 7.1 + * @param locale + * The locale for which to create a LocaleData object + * @return A LocaleData object with information about the given locale + */ + protected LocaleData createLocaleData(Locale locale) { + LocaleData localeData = new LocaleData(); + localeData.name = locale.toString(); + + final DateFormatSymbols dfs = new DateFormatSymbols(locale); + localeData.shortMonthNames = dfs.getShortMonths(); + localeData.monthNames = dfs.getMonths(); + // Client expects 0 based indexing, DateFormatSymbols use 1 based + localeData.shortDayNames = new String[7]; + localeData.dayNames = new String[7]; + String[] sDayNames = dfs.getShortWeekdays(); + String[] lDayNames = dfs.getWeekdays(); + for (int i = 0; i < 7; i++) { + localeData.shortDayNames[i] = sDayNames[i + 1]; + localeData.dayNames[i] = lDayNames[i + 1]; + } + + /* + * First day of week (0 = sunday, 1 = monday) + */ + final java.util.Calendar cal = new GregorianCalendar(locale); + localeData.firstDayOfWeek = cal.getFirstDayOfWeek() - 1; + + /* + * Date formatting (MM/DD/YYYY etc.) + */ + + DateFormat dateFormat = DateFormat.getDateTimeInstance( + DateFormat.SHORT, DateFormat.SHORT, locale); + if (!(dateFormat instanceof SimpleDateFormat)) { + getLogger().warning( + "Unable to get default date pattern for locale " + + locale.toString()); + dateFormat = new SimpleDateFormat(); + } + final String df = ((SimpleDateFormat) dateFormat).toPattern(); + + int timeStart = df.indexOf("H"); + if (timeStart < 0) { + timeStart = df.indexOf("h"); + } + final int ampm_first = df.indexOf("a"); + // E.g. in Korean locale AM/PM is before h:mm + // TODO should take that into consideration on client-side as well, + // now always h:mm a + if (ampm_first > 0 && ampm_first < timeStart) { + timeStart = ampm_first; + } + // Hebrew locale has time before the date + final boolean timeFirst = timeStart == 0; + String dateformat; + if (timeFirst) { + int dateStart = df.indexOf(' '); + if (ampm_first > dateStart) { + dateStart = df.indexOf(' ', ampm_first); + } + dateformat = df.substring(dateStart + 1); + } else { + dateformat = df.substring(0, timeStart - 1); + } + + localeData.dateFormat = dateformat.trim(); + + /* + * Time formatting (24 or 12 hour clock and AM/PM suffixes) + */ + final String timeformat = df.substring(timeStart, df.length()); + /* + * Doesn't return second or milliseconds. + * + * We use timeformat to determine 12/24-hour clock + */ + final boolean twelve_hour_clock = timeformat.indexOf("a") > -1; + // TODO there are other possibilities as well, like 'h' in french + // (ignore them, too complicated) + final String hour_min_delimiter = timeformat.indexOf(".") > -1 ? "." + : ":"; + // outWriter.print("\"tf\":\"" + timeformat + "\","); + localeData.twelveHourClock = twelve_hour_clock; + localeData.hourMinuteDelimiter = hour_min_delimiter; + if (twelve_hour_clock) { + final String[] ampm = dfs.getAmPmStrings(); + localeData.am = ampm[0]; + localeData.pm = ampm[1]; + } + + return localeData; + } + + private static Logger getLogger() { + return Logger.getLogger(LocaleService.class.getName()); + } + +} diff --git a/server/src/com/vaadin/server/Page.java b/server/src/com/vaadin/server/Page.java index d4c16fe7f7..11553527e0 100644 --- a/server/src/com/vaadin/server/Page.java +++ b/server/src/com/vaadin/server/Page.java @@ -21,11 +21,10 @@ import java.lang.reflect.Method; import java.net.URI; import java.net.URISyntaxException; import java.util.EventObject; -import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; -import java.util.Map; import com.vaadin.event.EventRouter; import com.vaadin.shared.ui.BorderStyle; @@ -307,6 +306,61 @@ public class Page implements Serializable { } } + private static interface InjectedStyle { + public void paint(int id, PaintTarget target) throws PaintException; + } + + private static class InjectedStyleString implements InjectedStyle { + + private String css; + + public InjectedStyleString(String css) { + this.css = css; + } + + @Override + public void paint(int id, PaintTarget target) throws PaintException { + target.startTag("css-string"); + target.addAttribute("id", id); + target.addText(css); + target.endTag("css-string"); + } + } + + private static class InjectedStyleResource implements InjectedStyle { + + private final Resource resource; + + public InjectedStyleResource(Resource resource) { + this.resource = resource; + } + + @Override + public void paint(int id, PaintTarget target) throws PaintException { + target.startTag("css-resource"); + target.addAttribute("id", id); + target.addAttribute("url", resource); + target.endTag("css-resource"); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof InjectedStyleResource) { + InjectedStyleResource that = (InjectedStyleResource) obj; + return resource.equals(that.resource); + } else { + return false; + } + } + + @Override + public int hashCode() { + return resource.hashCode(); + } + } + /** * Contains dynamically injected styles injected in the HTML document at * runtime. @@ -315,16 +369,9 @@ public class Page implements Serializable { */ public static class Styles implements Serializable { - private final Map<Integer, String> stringInjections = new HashMap<Integer, String>(); - - private final Map<Integer, Resource> resourceInjections = new HashMap<Integer, Resource>(); + private LinkedHashSet<InjectedStyle> injectedStyles = new LinkedHashSet<InjectedStyle>(); - // The combined injection counter between both string and resource - // injections. Used as the key for the injection maps - private int injectionCounter = 0; - - // Points to the next injection that has not yet been made into the Page - private int nextInjectionPosition = 0; + private LinkedHashSet<InjectedStyle> pendingInjections = new LinkedHashSet<InjectedStyle>(); private final UI ui; @@ -344,7 +391,7 @@ public class Page implements Serializable { "Cannot inject null CSS string"); } - stringInjections.put(injectionCounter++, css); + pendingInjections.add(new InjectedStyleString(css)); ui.markAsDirty(); } @@ -360,43 +407,33 @@ public class Page implements Serializable { "Cannot inject null resource"); } - resourceInjections.put(injectionCounter++, resource); - ui.markAsDirty(); + InjectedStyleResource injection = new InjectedStyleResource( + resource); + if (!injectedStyles.contains(injection) + && pendingInjections.add(injection)) { + ui.markAsDirty(); + } } private void paint(PaintTarget target) throws PaintException { // If full repaint repaint all injections if (target.isFullRepaint()) { - nextInjectionPosition = 0; + injectedStyles.addAll(pendingInjections); + pendingInjections = injectedStyles; + injectedStyles = new LinkedHashSet<InjectedStyle>(); } - if (injectionCounter > nextInjectionPosition) { + if (!pendingInjections.isEmpty()) { target.startTag("css-injections"); - while (injectionCounter > nextInjectionPosition) { - - String stringInjection = stringInjections - .get(nextInjectionPosition); - if (stringInjection != null) { - target.startTag("css-string"); - target.addAttribute("id", nextInjectionPosition); - target.addText(stringInjection); - target.endTag("css-string"); - } - - Resource resourceInjection = resourceInjections - .get(nextInjectionPosition); - if (resourceInjection != null) { - target.startTag("css-resource"); - target.addAttribute("id", nextInjectionPosition); - target.addAttribute("url", resourceInjection); - target.endTag("css-resource"); - } - - nextInjectionPosition++; + for (InjectedStyle pending : pendingInjections) { + int id = injectedStyles.size(); + pending.paint(id, target); + injectedStyles.add(pending); } + pendingInjections.clear(); target.endTag("css-injections"); } diff --git a/server/src/com/vaadin/server/RequestHandler.java b/server/src/com/vaadin/server/RequestHandler.java index 873752c5f2..097a3e034b 100644 --- a/server/src/com/vaadin/server/RequestHandler.java +++ b/server/src/com/vaadin/server/RequestHandler.java @@ -37,7 +37,8 @@ public interface RequestHandler extends Serializable { * using VaadinSession or anything inside the VaadinSession you must ensure * the session is locked. This can be done by extending * {@link SynchronizedRequestHandler} or by using - * {@link VaadinSession#access(Runnable)} or {@link UI#access(Runnable)}. + * {@link VaadinSession#accessSynchronously(Runnable)} or + * {@link UI#accessSynchronously(Runnable)}. * </p> * * @param session diff --git a/server/src/com/vaadin/server/UIProvider.java b/server/src/com/vaadin/server/UIProvider.java index 0305b907e6..3e7c85aea9 100644 --- a/server/src/com/vaadin/server/UIProvider.java +++ b/server/src/com/vaadin/server/UIProvider.java @@ -25,6 +25,7 @@ import com.vaadin.annotations.Theme; import com.vaadin.annotations.Title; import com.vaadin.annotations.Widgetset; import com.vaadin.shared.communication.PushMode; +import com.vaadin.shared.ui.ui.Transport; import com.vaadin.ui.UI; public abstract class UIProvider implements Serializable { @@ -174,4 +175,27 @@ public abstract class UIProvider implements Serializable { return push.value(); } } + + /** + * Finds the {@link Transport} to use for a specific UI. If no transport is + * defined, <code>null</code> is returned. + * <p> + * The default implementation uses the @{@link Push} annotation if it's + * defined for the UI class. + * + * @param event + * the UI create event with information about the UI and the + * current request. + * @return the transport type to use, or <code>null</code> if the default + * transport type should be used + */ + public Transport getPushTransport(UICreateEvent event) { + Push push = getAnnotationFor(event.getUIClass(), Push.class); + if (push == null) { + return null; + } else { + return push.transport(); + } + } + } diff --git a/server/src/com/vaadin/server/VaadinPortlet.java b/server/src/com/vaadin/server/VaadinPortlet.java index 327ce78a6c..d86e5e6507 100644 --- a/server/src/com/vaadin/server/VaadinPortlet.java +++ b/server/src/com/vaadin/server/VaadinPortlet.java @@ -287,7 +287,6 @@ public class VaadinPortlet extends GenericPortlet implements Constants, @Override public void init(PortletConfig config) throws PortletException { CurrentInstance.clearAll(); - setCurrent(this); super.init(config); Properties initParameters = new Properties(); @@ -407,7 +406,6 @@ public class VaadinPortlet extends GenericPortlet implements Constants, PortletResponse response) throws PortletException, IOException { CurrentInstance.clearAll(); - setCurrent(this); try { getService().handleRequest(createVaadinRequest(request), createVaadinResponse(response)); @@ -495,36 +493,23 @@ public class VaadinPortlet extends GenericPortlet implements Constants, * portlet is defined (see {@link InheritableThreadLocal}). In other cases, * (e.g. from background threads started in some other way), the current * portlet is not automatically defined. + * <p> + * The current portlet is derived from the current service using + * {@link VaadinService#getCurrent()} * * @return the current vaadin portlet instance if available, otherwise * <code>null</code> * - * @see #setCurrent(VaadinPortlet) - * * @since 7.0 */ public static VaadinPortlet getCurrent() { - return CurrentInstance.get(VaadinPortlet.class); - } - - /** - * Sets the current Vaadin portlet. This method is used by the framework to - * set the current portlet whenever a new request is processed and it is - * cleared when the request has been processed. - * <p> - * The application developer can also use this method to define the current - * portlet outside the normal request handling, e.g. when initiating custom - * background threads. - * </p> - * - * @param portlet - * the Vaadin portlet to register as the current portlet - * - * @see #getCurrent() - * @see InheritableThreadLocal - */ - public static void setCurrent(VaadinPortlet portlet) { - CurrentInstance.setInheritable(VaadinPortlet.class, portlet); + VaadinService vaadinService = CurrentInstance.get(VaadinService.class); + if (vaadinService instanceof VaadinPortletService) { + VaadinPortletService vps = (VaadinPortletService) vaadinService; + return vps.getPortlet(); + } else { + return null; + } } } diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java index af0c280c19..a040c72175 100644 --- a/server/src/com/vaadin/server/VaadinService.java +++ b/server/src/com/vaadin/server/VaadinService.java @@ -33,6 +33,9 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; @@ -47,6 +50,7 @@ import org.json.JSONObject; import com.vaadin.annotations.PreserveOnRefresh; import com.vaadin.event.EventRouter; +import com.vaadin.server.VaadinSession.FutureAccess; import com.vaadin.server.communication.FileUploadHandler; import com.vaadin.server.communication.HeartbeatHandler; import com.vaadin.server.communication.PublishedFileHandler; @@ -110,6 +114,11 @@ public abstract class VaadinService implements Serializable { private boolean pushWarningEmitted = false; /** + * Has {@link #init()} been run? + */ + private boolean initialized = false; + + /** * Creates a new vaadin service based on a deployment configuration * * @param deploymentConfiguration @@ -148,6 +157,8 @@ public abstract class VaadinService implements Serializable { List<RequestHandler> handlers = createRequestHandlers(); Collections.reverse(handlers); requestHandlers = Collections.unmodifiableCollection(handlers); + + initialized = true; } /** @@ -407,12 +418,12 @@ public abstract class VaadinService implements Serializable { */ public void fireSessionDestroy(VaadinSession vaadinSession) { final VaadinSession session = vaadinSession; - session.access(new Runnable() { + session.accessSynchronously(new Runnable() { @Override public void run() { ArrayList<UI> uis = new ArrayList<UI>(session.getUIs()); for (final UI ui : uis) { - ui.access(new Runnable() { + ui.accessSynchronously(new Runnable() { @Override public void run() { /* @@ -1087,7 +1098,7 @@ public abstract class VaadinService implements Serializable { private void removeClosedUIs(final VaadinSession session) { ArrayList<UI> uis = new ArrayList<UI>(session.getUIs()); for (final UI ui : uis) { - ui.access(new Runnable() { + ui.accessSynchronously(new Runnable() { @Override public void run() { if (ui.isClosing()) { @@ -1224,6 +1235,10 @@ public abstract class VaadinService implements Serializable { * The response */ public void requestStart(VaadinRequest request, VaadinResponse response) { + if (!initialized) { + throw new IllegalStateException( + "Can not process requests before init() has been called"); + } setCurrentInstances(request, response); request.setAttribute(REQUEST_START_TIME_ATTRIBUTE, System.nanoTime()); } @@ -1245,7 +1260,7 @@ public abstract class VaadinService implements Serializable { if (session != null) { final VaadinSession finalSession = session; - session.access(new Runnable() { + session.accessSynchronously(new Runnable() { @Override public void run() { cleanupSession(finalSession); @@ -1254,7 +1269,7 @@ public abstract class VaadinService implements Serializable { final long duration = (System.nanoTime() - (Long) request .getAttribute(REQUEST_START_TIME_ATTRIBUTE)) / 1000000; - session.access(new Runnable() { + session.accessSynchronously(new Runnable() { @Override public void run() { finalSession.setLastRequestDuration(duration); @@ -1542,8 +1557,9 @@ public abstract class VaadinService implements Serializable { /** * Checks that another {@link VaadinSession} instance is not locked. This is - * internally used by {@link VaadinSession#access(Runnable)} and - * {@link UI#access(Runnable)} to help avoid causing deadlocks. + * internally used by {@link VaadinSession#accessSynchronously(Runnable)} + * and {@link UI#accessSynchronously(Runnable)} to help avoid causing + * deadlocks. * * @since 7.1 * @param session @@ -1597,4 +1613,88 @@ public abstract class VaadinService implements Serializable { return true; } + /** + * Implementation for {@link VaadinSession#access(Runnable)}. This method is + * implemented here instead of in {@link VaadinSession} to enable overriding + * the implementation without using a custom subclass of VaadinSession. + * + * @since 7.1 + * @see VaadinSession#access(Runnable) + * + * @param session + * the vaadin session to access + * @param runnable + * the runnable to run with the session locked + * + * @return a future that can be used to check for task completion and to + * cancel the task + */ + public Future<Void> accessSession(VaadinSession session, Runnable runnable) { + FutureAccess future = new FutureAccess(session, runnable); + session.getPendingAccessQueue().add(future); + + /* + * If no thread is currently holding the lock, pending changes for UIs + * with automatic push would not be processed and pushed until the next + * time there is a request or someone does an explicit push call. + * + * To remedy this, we try to get the lock at this point. If the lock is + * currently held by another thread, we just back out as the queue will + * get purged once it is released. If the lock is held by the current + * thread, we just release it knowing that the queue gets purged once + * the lock is ultimately released. If the lock is not held by any + * thread and we acquire it, we just release it again to purge the queue + * right away. + */ + try { + // tryLock() would be shorter, but it does not guarantee fairness + if (session.getLockInstance().tryLock(0, TimeUnit.SECONDS)) { + // unlock triggers runPendingAccessTasks + session.unlock(); + } + } catch (InterruptedException e) { + // Just ignore + } + + return future; + } + + /** + * Purges the queue of pending access invocations enqueued with + * {@link VaadinSession#access(Runnable)}. + * <p> + * This method is automatically run by the framework at appropriate + * situations and is not intended to be used by application developers. + * + * @param session + * the vaadin session to purge the queue for + * @since 7.1 + */ + public void runPendingAccessTasks(VaadinSession session) { + assert session.hasLock(); + + if (session.getPendingAccessQueue().isEmpty()) { + return; + } + + Map<Class<?>, CurrentInstance> oldInstances = CurrentInstance + .getInstances(false); + + FutureAccess pendingAccess; + try { + while ((pendingAccess = session.getPendingAccessQueue().poll()) != null) { + if (!pendingAccess.isCancelled()) { + CurrentInstance.clearAll(); + CurrentInstance.restoreInstances(pendingAccess + .getCurrentInstances()); + CurrentInstance.setCurrent(session); + pendingAccess.run(); + } + } + } finally { + CurrentInstance.clearAll(); + CurrentInstance.restoreInstances(oldInstances); + } + } + } diff --git a/server/src/com/vaadin/server/VaadinServlet.java b/server/src/com/vaadin/server/VaadinServlet.java index de074941c1..05e3335c00 100644 --- a/server/src/com/vaadin/server/VaadinServlet.java +++ b/server/src/com/vaadin/server/VaadinServlet.java @@ -21,6 +21,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; +import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; @@ -38,6 +39,8 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import com.vaadin.annotations.VaadinServletConfiguration; +import com.vaadin.annotations.VaadinServletConfiguration.InitParameterName; import com.vaadin.sass.internal.ScssStylesheet; import com.vaadin.server.communication.ServletUIInitHandler; import com.vaadin.shared.JsonConstants; @@ -63,10 +66,11 @@ public class VaadinServlet extends HttpServlet implements Constants { public void init(javax.servlet.ServletConfig servletConfig) throws ServletException { CurrentInstance.clearAll(); - setCurrent(this); super.init(servletConfig); Properties initParameters = new Properties(); + readConfigurationAnnotation(initParameters); + // Read default parameters from server.xml final ServletContext context = servletConfig.getServletContext(); for (final Enumeration<String> e = context.getInitParameterNames(); e @@ -97,6 +101,39 @@ public class VaadinServlet extends HttpServlet implements Constants { CurrentInstance.clearAll(); } + private void readConfigurationAnnotation(Properties initParameters) + throws ServletException { + VaadinServletConfiguration configAnnotation = UIProvider + .getAnnotationFor(getClass(), VaadinServletConfiguration.class); + if (configAnnotation != null) { + Method[] methods = VaadinServletConfiguration.class + .getDeclaredMethods(); + for (Method method : methods) { + InitParameterName name = method + .getAnnotation(InitParameterName.class); + assert name != null : "All methods declared in VaadinServletConfiguration should have a @InitParameterName annotation"; + + try { + Object value = method.invoke(configAnnotation); + + String stringValue; + if (value instanceof Class<?>) { + stringValue = ((Class<?>) value).getName(); + } else { + stringValue = value.toString(); + } + + initParameters.setProperty(name.value(), stringValue); + } catch (Exception e) { + // This should never happen + throw new ServletException( + "Could not read @VaadinServletConfiguration value " + + method.getName(), e); + } + } + } + } + protected void servletInitialized() throws ServletException { // Empty by default } @@ -108,36 +145,23 @@ public class VaadinServlet extends HttpServlet implements Constants { * servlet is defined (see {@link InheritableThreadLocal}). In other cases, * (e.g. from background threads started in some other way), the current * servlet is not automatically defined. + * <p> + * The current servlet is derived from the current service using + * {@link VaadinService#getCurrent()} * * @return the current Vaadin servlet instance if available, otherwise * <code>null</code> * - * @see #setCurrent(VaadinServlet) - * * @since 7.0 */ public static VaadinServlet getCurrent() { - return CurrentInstance.get(VaadinServlet.class); - } - - /** - * Sets the current Vaadin servlet. This method is used by the framework to - * set the current servlet whenever a new request is processed and it is - * cleared when the request has been processed. - * <p> - * The application developer can also use this method to define the current - * servlet outside the normal request handling, e.g. when initiating custom - * background threads. - * </p> - * - * @param servlet - * the Vaadin servlet to register as the current servlet - * - * @see #getCurrent() - * @see InheritableThreadLocal - */ - public static void setCurrent(VaadinServlet servlet) { - CurrentInstance.setInheritable(VaadinServlet.class, servlet); + VaadinService vaadinService = CurrentInstance.get(VaadinService.class); + if (vaadinService instanceof VaadinServletService) { + VaadinServletService vss = (VaadinServletService) vaadinService; + return vss.getServlet(); + } else { + return null; + } } protected DeploymentConfiguration createDeploymentConfiguration( @@ -179,7 +203,6 @@ public class VaadinServlet extends HttpServlet implements Constants { return; } CurrentInstance.clearAll(); - setCurrent(this); VaadinServletRequest vaadinRequest = createVaadinRequest(request); VaadinServletResponse vaadinResponse = createVaadinResponse(response); @@ -188,8 +211,14 @@ public class VaadinServlet extends HttpServlet implements Constants { } if (isStaticResourceRequest(request)) { - serveStaticResources(request, response); - return; + // Define current servlet and service, but no request and response + getService().setCurrentInstances(null, null); + try { + serveStaticResources(request, response); + return; + } finally { + CurrentInstance.clearAll(); + } } try { getService().handleRequest(vaadinRequest, vaadinResponse); diff --git a/server/src/com/vaadin/server/VaadinSession.java b/server/src/com/vaadin/server/VaadinSession.java index 317ea6cf7b..e0a5b51baa 100644 --- a/server/src/com/vaadin/server/VaadinSession.java +++ b/server/src/com/vaadin/server/VaadinSession.java @@ -25,7 +25,12 @@ import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Queue; import java.util.UUID; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Logger; @@ -63,6 +68,68 @@ import com.vaadin.util.ReflectTools; public class VaadinSession implements HttpSessionBindingListener, Serializable { /** + * Encapsulates a {@link Runnable} submitted using + * {@link VaadinSession#access(Runnable)}. This class is used internally by + * the framework and is not intended to be directly used by application + * developers. + * + * @since 7.1 + * @author Vaadin Ltd + */ + public static class FutureAccess extends FutureTask<Void> { + /** + * Snapshot of all non-inheritable current instances at the time this + * object was created. + */ + private final Map<Class<?>, CurrentInstance> instances = CurrentInstance + .getInstances(true); + private final VaadinSession session; + + /** + * Creates an instance for the given runnable + * + * @param session + * the session to which the task belongs + * + * @param runnable + * the runnable to run when this task is purged from the + * queue + */ + public FutureAccess(VaadinSession session, Runnable runnable) { + super(runnable, null); + this.session = session; + } + + @Override + public Void get() throws InterruptedException, ExecutionException { + /* + * Help the developer avoid programming patterns that cause + * deadlocks unless implemented very carefully. get(long, TimeUnit) + * does not have the same detection since a sensible timeout should + * avoid completely locking up the application. + * + * Even though no deadlock could occur after the runnable has been + * run, the check is always done as the deterministic behavior makes + * it easier to detect potential problems. + */ + VaadinService.verifyNoOtherSessionLocked(session); + return super.get(); + } + + /** + * Gets the current instance values that should be used when running + * this task. + * + * @see CurrentInstance#restoreInstances(Map) + * + * @return a map of current instances. + */ + public Map<Class<?>, CurrentInstance> getCurrentInstances() { + return instances; + } + } + + /** * The name of the parameter that is by default used in e.g. web.xml to * define the name of the default {@link UI} class. */ @@ -130,6 +197,13 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { private transient Lock lock; + /* + * Pending tasks can't be serialized and the queue should be empty when the + * session is serialized as long as it doesn't happen while some other + * thread has the lock. + */ + private transient final ConcurrentLinkedQueue<FutureAccess> pendingAccessQueue = new ConcurrentLinkedQueue<FutureAccess>(); + /** * Create a new service session tied to a Vaadin service * @@ -189,9 +263,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Get the web browser associated with this session. * - * @return - * @deprecated As of 7.0. Will likely change or be removed in a future - * version + * @return the web browser object + * + * @deprecated As of 7.0, use {@link Page#getWebBrowser()} instead. */ @Deprecated public WebBrowser getBrowser() { @@ -820,11 +894,15 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { public void unlock() { assert hasLock(); try { + /* + * Run pending tasks and push if the reentrant lock will actually be + * released by this unlock() invocation. + */ if (((ReentrantLock) getLockInstance()).getHoldCount() == 1) { - // Only push if the reentrant lock will actually be released by - // this unlock() invocation. + getService().runPendingAccessTasks(this); + for (UI ui : getUIs()) { - if (ui.getPushMode() == PushMode.AUTOMATIC) { + if (ui.getPushConfiguration().getPushMode() == PushMode.AUTOMATIC) { ui.push(); } } @@ -1063,23 +1141,26 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { } /** - * Provides exclusive access to this session from outside a request handling - * thread. + * Locks this session and runs the provided Runnable right away. * <p> - * The given runnable is executed while holding the session lock to ensure - * exclusive access to this session. The session and related thread locals - * are set properly before executing the runnable. - * </p> - * <p> - * RPC handlers for components inside this session do not need this method - * as the session is automatically locked by the framework during request - * handling. + * It is generally recommended to use {@link #access(Runnable)} instead of + * this method for accessing a session from a different thread as + * {@link #access(Runnable)} can be used while holding the lock of another + * session. To avoid causing deadlocks, this methods throws an exception if + * it is detected than another session is also locked by the current thread. * </p> * <p> - * Note that calling this method while another session is locked by the - * current thread will cause an exception. This is to prevent deadlock - * situations when two threads have locked one session each and are both - * waiting for the lock for the other session. + * This method behaves differently than {@link #access(Runnable)} in some + * situations: + * <ul> + * <li>If the current thread is currently holding the lock of this session, + * {@link #accessSynchronously(Runnable)} runs the task right away whereas + * {@link #access(Runnable)} defers the task to a later point in time.</li> + * <li>If some other thread is currently holding the lock for this session, + * {@link #accessSynchronously(Runnable)} blocks while waiting for the lock + * to be available whereas {@link #access(Runnable)} defers the task to a + * later point in time.</li> + * </ul> * </p> * * @param runnable @@ -1088,35 +1169,87 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * @throws IllegalStateException * if the current thread holds the lock for another session * + * @since 7.1 * * @see #lock() * @see #getCurrent() - * @see UI#access(Runnable) + * @see #access(Runnable) + * @see UI#accessSynchronously(Runnable) */ - public void access(Runnable runnable) { + public void accessSynchronously(Runnable runnable) { VaadinService.verifyNoOtherSessionLocked(this); Map<Class<?>, CurrentInstance> old = null; lock(); try { - old = CurrentInstance.setThreadLocals(this); + old = CurrentInstance.setCurrent(this); runnable.run(); } finally { unlock(); if (old != null) { - CurrentInstance.restoreThreadLocals(old); + CurrentInstance.restoreInstances(old); } } } /** - * @deprecated As of 7.1.0.beta1, use {@link #access(Runnable)} instead. - * This method will be removed before the final 7.1.0 release. + * Provides exclusive access to this session from outside a request handling + * thread. + * <p> + * The given runnable is executed while holding the session lock to ensure + * exclusive access to this session. If this session is not locked, the lock + * will be acquired and the runnable is run right away. If this session is + * currently locked, the runnable will be run before that lock is released. + * </p> + * <p> + * RPC handlers for components inside this session do not need to use this + * method as the session is automatically locked by the framework during RPC + * handling. + * </p> + * <p> + * Please note that the runnable might be invoked on a different thread or + * later on the current thread, which means that custom thread locals might + * not have the expected values when the runnable is executed. Inheritable + * values in {@link CurrentInstance} will have the same values as when this + * method was invoked. {@link VaadinSession#getCurrent()} and + * {@link VaadinService#getCurrent()} are set according to this session + * before executing the runnable. Non-inheritable CurrentInstance values + * including {@link VaadinService#getCurrentRequest()} and + * {@link VaadinService#getCurrentResponse()} will not be defined. + * </p> + * <p> + * The returned future can be used to check for task completion and to + * cancel the task. To help avoiding deadlocks, {@link Future#get()} throws + * an exception if it is detected that the current thread holds the lock for + * some other session. + * </p> + * + * @see #lock() + * @see #getCurrent() + * @see #accessSynchronously(Runnable) + * @see UI#access(Runnable) + * + * @since 7.1 + * + * @param runnable + * the runnable which accesses the session + * @return a future that can be used to check for task completion and to + * cancel the task */ - @Deprecated - public void runSafely(Runnable runnable) { - access(runnable); + public Future<Void> access(Runnable runnable) { + return getService().accessSession(this, runnable); + } + + /** + * Gets the queue of tasks submitted using {@link #access(Runnable)}. + * + * @since 7.1 + * + * @return the pending access queue + */ + public Queue<FutureAccess> getPendingAccessQueue() { + return pendingAccessQueue; } /** diff --git a/server/src/com/vaadin/server/communication/AtmospherePushConnection.java b/server/src/com/vaadin/server/communication/AtmospherePushConnection.java index 0bba65ff1d..9e57ccb45d 100644 --- a/server/src/com/vaadin/server/communication/AtmospherePushConnection.java +++ b/server/src/com/vaadin/server/communication/AtmospherePushConnection.java @@ -32,7 +32,7 @@ import org.atmosphere.cpr.AtmosphereResource; import org.atmosphere.cpr.AtmosphereResource.TRANSPORT; import org.json.JSONException; -import com.vaadin.shared.ApplicationConstants; +import com.vaadin.shared.communication.PushConstants; import com.vaadin.ui.UI; /** @@ -42,21 +42,22 @@ import com.vaadin.ui.UI; * @author Vaadin Ltd * @since 7.1 */ -public class AtmospherePushConnection implements Serializable, PushConnection { +public class AtmospherePushConnection implements PushConnection { /** * Represents a message that can arrive as multiple fragments. */ - protected static class FragmentedMessage { + protected static class FragmentedMessage implements Serializable { private final StringBuilder message = new StringBuilder(); private final int messageLength; public FragmentedMessage(Reader reader) throws IOException { - // Messages are prefixed by the total message length plus '|' + // Messages are prefixed by the total message length plus a + // delimiter String length = ""; int c; while ((c = reader.read()) != -1 - && c != ApplicationConstants.WEBSOCKET_MESSAGE_DELIMITER) { + && c != PushConstants.MESSAGE_DELIMITER) { length += (char) c; } try { @@ -76,7 +77,7 @@ public class AtmospherePushConnection implements Serializable, PushConnection { * @throws IOException */ public boolean append(Reader reader) throws IOException { - char[] buffer = new char[ApplicationConstants.WEBSOCKET_BUFFER_SIZE]; + char[] buffer = new char[PushConstants.WEBSOCKET_BUFFER_SIZE]; int read; while ((read = reader.read(buffer)) != -1) { message.append(buffer, 0, read); @@ -122,7 +123,7 @@ public class AtmospherePushConnection implements Serializable, PushConnection { protected void push(boolean async) throws IOException { Writer writer = new StringWriter(); try { - new UidlWriter().write(getUI(), writer, false, false, async); + new UidlWriter().write(getUI(), writer, false, async); } catch (JSONException e) { throw new IOException("Error writing UIDL", e); } diff --git a/server/src/com/vaadin/server/communication/FileUploadHandler.java b/server/src/com/vaadin/server/communication/FileUploadHandler.java index e875a4e861..e9569d45a1 100644 --- a/server/src/com/vaadin/server/communication/FileUploadHandler.java +++ b/server/src/com/vaadin/server/communication/FileUploadHandler.java @@ -632,7 +632,7 @@ public class FileUploadHandler implements RequestHandler { private void cleanStreamVariable(VaadinSession session, final ClientConnector owner, final String variableName) { - session.access(new Runnable() { + session.accessSynchronously(new Runnable() { @Override public void run() { owner.getUI() diff --git a/server/src/com/vaadin/server/communication/LocaleWriter.java b/server/src/com/vaadin/server/communication/LocaleWriter.java deleted file mode 100644 index c05649da19..0000000000 --- a/server/src/com/vaadin/server/communication/LocaleWriter.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2000-2013 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.server.communication; - -import java.io.IOException; -import java.io.Serializable; -import java.io.Writer; -import java.text.DateFormat; -import java.text.DateFormatSymbols; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.List; -import java.util.Locale; -import java.util.logging.Logger; - -/** - * Serializes locale information to JSON. - * - * @author Vaadin Ltd - * @since 7.1 - * @deprecated See <a href="http://dev.vaadin.com/ticket/11378">ticket - * #11378</a>. - */ -@Deprecated -public class LocaleWriter implements Serializable { - - /** - * Writes a JSON object containing localized strings of the given locales. - * - * @param locales - * The list of {@link Locale}s to write. - * @param writer - * The {@link Writer} used to write the JSON. - * @throws IOException - * If the serialization fails. - * - */ - public void write(List<String> locales, Writer writer) throws IOException { - - // Send locale informations to client - writer.write("["); - // TODO locales are currently sent on each request; this will be fixed - // by implementing #11378. - for (int pendingLocalesIndex = 0; pendingLocalesIndex < locales.size(); pendingLocalesIndex++) { - - final Locale l = generateLocale(locales.get(pendingLocalesIndex)); - // Locale name - writer.write("{\"name\":\"" + l.toString() + "\","); - - /* - * Month names (both short and full) - */ - final DateFormatSymbols dfs = new DateFormatSymbols(l); - final String[] short_months = dfs.getShortMonths(); - final String[] months = dfs.getMonths(); - writer.write("\"smn\":[\"" - + // ShortMonthNames - short_months[0] + "\",\"" + short_months[1] + "\",\"" - + short_months[2] + "\",\"" + short_months[3] + "\",\"" - + short_months[4] + "\",\"" + short_months[5] + "\",\"" - + short_months[6] + "\",\"" + short_months[7] + "\",\"" - + short_months[8] + "\",\"" + short_months[9] + "\",\"" - + short_months[10] + "\",\"" + short_months[11] + "\"" - + "],"); - writer.write("\"mn\":[\"" - + // MonthNames - months[0] + "\",\"" + months[1] + "\",\"" + months[2] - + "\",\"" + months[3] + "\",\"" + months[4] + "\",\"" - + months[5] + "\",\"" + months[6] + "\",\"" + months[7] - + "\",\"" + months[8] + "\",\"" + months[9] + "\",\"" - + months[10] + "\",\"" + months[11] + "\"" + "],"); - - /* - * Weekday names (both short and full) - */ - final String[] short_days = dfs.getShortWeekdays(); - final String[] days = dfs.getWeekdays(); - writer.write("\"sdn\":[\"" - + // ShortDayNames - short_days[1] + "\",\"" + short_days[2] + "\",\"" - + short_days[3] + "\",\"" + short_days[4] + "\",\"" - + short_days[5] + "\",\"" + short_days[6] + "\",\"" - + short_days[7] + "\"" + "],"); - writer.write("\"dn\":[\"" - + // DayNames - days[1] + "\",\"" + days[2] + "\",\"" + days[3] + "\",\"" - + days[4] + "\",\"" + days[5] + "\",\"" + days[6] + "\",\"" - + days[7] + "\"" + "],"); - - /* - * First day of week (0 = sunday, 1 = monday) - */ - final Calendar cal = new GregorianCalendar(l); - writer.write("\"fdow\":" + (cal.getFirstDayOfWeek() - 1) + ","); - - /* - * Date formatting (MM/DD/YYYY etc.) - */ - - DateFormat dateFormat = DateFormat.getDateTimeInstance( - DateFormat.SHORT, DateFormat.SHORT, l); - if (!(dateFormat instanceof SimpleDateFormat)) { - getLogger().warning( - "Unable to get default date pattern for locale " - + l.toString()); - dateFormat = new SimpleDateFormat(); - } - final String df = ((SimpleDateFormat) dateFormat).toPattern(); - - int timeStart = df.indexOf("H"); - if (timeStart < 0) { - timeStart = df.indexOf("h"); - } - final int ampm_first = df.indexOf("a"); - // E.g. in Korean locale AM/PM is before h:mm - // TODO should take that into consideration on client-side as well, - // now always h:mm a - if (ampm_first > 0 && ampm_first < timeStart) { - timeStart = ampm_first; - } - // Hebrew locale has time before the date - final boolean timeFirst = timeStart == 0; - String dateformat; - if (timeFirst) { - int dateStart = df.indexOf(' '); - if (ampm_first > dateStart) { - dateStart = df.indexOf(' ', ampm_first); - } - dateformat = df.substring(dateStart + 1); - } else { - dateformat = df.substring(0, timeStart - 1); - } - - writer.write("\"df\":\"" + dateformat.trim() + "\","); - - /* - * Time formatting (24 or 12 hour clock and AM/PM suffixes) - */ - final String timeformat = df.substring(timeStart, df.length()); - /* - * Doesn't return second or milliseconds. - * - * We use timeformat to determine 12/24-hour clock - */ - final boolean twelve_hour_clock = timeformat.indexOf("a") > -1; - // TODO there are other possibilities as well, like 'h' in french - // (ignore them, too complicated) - final String hour_min_delimiter = timeformat.indexOf(".") > -1 ? "." - : ":"; - // outWriter.print("\"tf\":\"" + timeformat + "\","); - writer.write("\"thc\":" + twelve_hour_clock + ","); - writer.write("\"hmd\":\"" + hour_min_delimiter + "\""); - if (twelve_hour_clock) { - final String[] ampm = dfs.getAmPmStrings(); - writer.write(",\"ampm\":[\"" + ampm[0] + "\",\"" + ampm[1] - + "\"]"); - } - writer.write("}"); - if (pendingLocalesIndex < locales.size() - 1) { - writer.write(","); - } - } - writer.write("]"); // Close locales - } - - /** - * Constructs a {@link Locale} instance to be sent to the client based on a - * short locale description string. - * - * @see #requireLocale(String) - * - * @param value - * @return - */ - private Locale generateLocale(String value) { - final String[] temp = value.split("_"); - if (temp.length == 1) { - return new Locale(temp[0]); - } else if (temp.length == 2) { - return new Locale(temp[0], temp[1]); - } else { - return new Locale(temp[0], temp[1], temp[2]); - } - } - - private static final Logger getLogger() { - return Logger.getLogger(LocaleWriter.class.getName()); - } -} diff --git a/server/src/com/vaadin/server/communication/MetadataWriter.java b/server/src/com/vaadin/server/communication/MetadataWriter.java index 1a3f0e946a..5ad7186c24 100644 --- a/server/src/com/vaadin/server/communication/MetadataWriter.java +++ b/server/src/com/vaadin/server/communication/MetadataWriter.java @@ -17,17 +17,11 @@ package com.vaadin.server.communication; import java.io.IOException; -import java.io.PrintWriter; import java.io.Serializable; import java.io.Writer; -import java.util.List; -import com.vaadin.server.ClientConnector; -import com.vaadin.server.ComponentSizeValidator; -import com.vaadin.server.ComponentSizeValidator.InvalidLayout; import com.vaadin.server.SystemMessages; import com.vaadin.ui.UI; -import com.vaadin.ui.Window; /** * Serializes miscellaneous metadata to JSON. @@ -54,9 +48,6 @@ public class MetadataWriter implements Serializable { * @param async * True if this message is sent by the server asynchronously, * false if it is a response to a client message. - * @param hilightedConnector - * The connector that should be highlighted on the client or null - * if none. * @param messages * a {@link SystemMessages} containing client-side error * messages. @@ -64,27 +55,8 @@ public class MetadataWriter implements Serializable { * If the serialization fails. * */ - public void write(UI ui, Writer writer, boolean repaintAll, - boolean analyzeLayouts, boolean async, - ClientConnector hilightedConnector, SystemMessages messages) - throws IOException { - - List<InvalidLayout> invalidComponentRelativeSizes = null; - - if (analyzeLayouts) { - invalidComponentRelativeSizes = ComponentSizeValidator - .validateComponentRelativeSizes(ui.getContent(), null, null); - - // Also check any existing subwindows - if (ui.getWindows() != null) { - for (Window subWindow : ui.getWindows()) { - invalidComponentRelativeSizes = ComponentSizeValidator - .validateComponentRelativeSizes( - subWindow.getContent(), - invalidComponentRelativeSizes, null); - } - } - } + public void write(UI ui, Writer writer, boolean repaintAll, boolean async, + SystemMessages messages) throws IOException { writer.write("{"); @@ -92,28 +64,6 @@ public class MetadataWriter implements Serializable { if (repaintAll) { metaOpen = true; writer.write("\"repaintAll\":true"); - if (analyzeLayouts) { - writer.write(", \"invalidLayouts\":"); - writer.write("["); - if (invalidComponentRelativeSizes != null) { - boolean first = true; - for (InvalidLayout invalidLayout : invalidComponentRelativeSizes) { - if (!first) { - writer.write(","); - } else { - first = false; - } - invalidLayout.reportErrors(new PrintWriter(writer), - System.err); - } - } - writer.write("]"); - } - if (hilightedConnector != null) { - writer.write(", \"hl\":\""); - writer.write(hilightedConnector.getConnectorId()); - writer.write("\""); - } } if (async) { diff --git a/server/src/com/vaadin/server/communication/PushConnection.java b/server/src/com/vaadin/server/communication/PushConnection.java index 4e043f565f..bb88998402 100644 --- a/server/src/com/vaadin/server/communication/PushConnection.java +++ b/server/src/com/vaadin/server/communication/PushConnection.java @@ -16,6 +16,8 @@ package com.vaadin.server.communication; +import java.io.Serializable; + import com.vaadin.ui.UI; /** @@ -25,7 +27,7 @@ import com.vaadin.ui.UI; * @author Vaadin Ltd * @since 7.1 */ -public interface PushConnection { +public interface PushConnection extends Serializable { /** * Pushes pending state changes and client RPC calls to the client. It is diff --git a/server/src/com/vaadin/server/communication/PushHandler.java b/server/src/com/vaadin/server/communication/PushHandler.java index e740db410d..7efcb8fd8c 100644 --- a/server/src/com/vaadin/server/communication/PushHandler.java +++ b/server/src/com/vaadin/server/communication/PushHandler.java @@ -84,6 +84,13 @@ public class PushHandler implements AtmosphereHandler { if (browser.isIE() && browser.getBrowserMajorVersion() == 8) { resource.padding(LONG_PADDING); } + + // Must ensure that the streaming response contains + // "Connection: close", otherwise iOS 6 will wait for the + // response to this request before sending another request to + // the same server (as it will apparently try to reuse the same + // connection) + resource.getResponse().addHeader("Connection", "close"); } String requestToken = resource.getRequest().getParameter( @@ -164,7 +171,7 @@ public class PushHandler implements AtmosphereHandler { PushEventCallback disconnectCallback = new PushEventCallback() { @Override public void run(AtmosphereResource resource, UI ui) throws IOException { - PushMode pushMode = ui.getPushMode(); + PushMode pushMode = ui.getPushConfiguration().getPushMode(); AtmospherePushConnection pushConnection = getConnectionForUI(ui); String id = resource.uuid(); @@ -331,9 +338,9 @@ public class PushHandler implements AtmosphereHandler { writer.write(event.getMessage().toString()); switch (resource.transport()) { - case SSE: case WEBSOCKET: break; + case SSE: case STREAMING: writer.flush(); break; diff --git a/server/src/com/vaadin/server/communication/PushRequestHandler.java b/server/src/com/vaadin/server/communication/PushRequestHandler.java index 8360e08af9..8d0da24896 100644 --- a/server/src/com/vaadin/server/communication/PushRequestHandler.java +++ b/server/src/com/vaadin/server/communication/PushRequestHandler.java @@ -23,6 +23,7 @@ import javax.servlet.ServletException; import org.atmosphere.client.TrackMessageSizeInterceptor; import org.atmosphere.cpr.ApplicationConfig; import org.atmosphere.cpr.AtmosphereFramework; +import org.atmosphere.cpr.AtmosphereInterceptor; import org.atmosphere.cpr.AtmosphereRequest; import org.atmosphere.cpr.AtmosphereResponse; @@ -36,7 +37,7 @@ import com.vaadin.server.VaadinServletRequest; import com.vaadin.server.VaadinServletResponse; import com.vaadin.server.VaadinServletService; import com.vaadin.server.VaadinSession; -import com.vaadin.shared.ApplicationConstants; +import com.vaadin.shared.communication.PushConstants; /** * Handles requests to open a push (bidirectional) communication channel between @@ -55,15 +56,22 @@ public class PushRequestHandler implements RequestHandler, public PushRequestHandler(VaadinServletService service) throws ServiceException { - atmosphere = new AtmosphereFramework(); + atmosphere = new AtmosphereFramework() { + @Override + protected void analytics() { + // Overridden to disable version number check + } + }; pushHandler = new PushHandler(service); atmosphere.addAtmosphereHandler("/*", pushHandler); atmosphere.addInitParameter(ApplicationConfig.PROPERTY_SESSION_SUPPORT, "true"); + atmosphere.addInitParameter(ApplicationConfig.MESSAGE_DELIMITER, + String.valueOf(PushConstants.MESSAGE_DELIMITER)); final String bufferSize = String - .valueOf(ApplicationConstants.WEBSOCKET_BUFFER_SIZE); + .valueOf(PushConstants.WEBSOCKET_BUFFER_SIZE); atmosphere.addInitParameter(ApplicationConfig.WEBSOCKET_BUFFER_SIZE, bufferSize); atmosphere.addInitParameter(ApplicationConfig.WEBSOCKET_MAXTEXTSIZE, @@ -75,12 +83,14 @@ public class PushRequestHandler implements RequestHandler, atmosphere.addInitParameter("org.atmosphere.cpr.showSupportMessage", "false"); - // Required to ensure the client-side knows at which points to split the - // message stream into individual messages when using certain transports - atmosphere.interceptor(new TrackMessageSizeInterceptor()); - try { atmosphere.init(service.getServlet().getServletConfig()); + + // Ensure the client-side knows how to split the message stream + // into individual messages when using certain transports + AtmosphereInterceptor trackMessageSize = new TrackMessageSizeInterceptor(); + trackMessageSize.configure(atmosphere.getAtmosphereConfig()); + atmosphere.interceptor(trackMessageSize); } catch (ServletException e) { throw new ServiceException("Could not read atmosphere settings", e); } diff --git a/server/src/com/vaadin/server/communication/UIInitHandler.java b/server/src/com/vaadin/server/communication/UIInitHandler.java index e4b5360b49..d4b0bc709f 100644 --- a/server/src/com/vaadin/server/communication/UIInitHandler.java +++ b/server/src/com/vaadin/server/communication/UIInitHandler.java @@ -39,6 +39,7 @@ import com.vaadin.server.VaadinService; import com.vaadin.server.VaadinSession; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.communication.PushMode; +import com.vaadin.shared.ui.ui.Transport; import com.vaadin.shared.ui.ui.UIConstants; import com.vaadin.ui.UI; @@ -209,7 +210,12 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler { pushMode = session.getService().getDeploymentConfiguration() .getPushMode(); } - ui.setPushMode(pushMode); + ui.getPushConfiguration().setPushMode(pushMode); + + Transport transport = provider.getPushTransport(event); + if (transport != null) { + ui.getPushConfiguration().setTransport(transport); + } // Set thread local here so it is available in init UI.setCurrent(ui); @@ -273,7 +279,7 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler { if (session.getConfiguration().isXsrfProtectionEnabled()) { writer.write(getSecurityKeyUIDL(session)); } - new UidlWriter().write(uI, writer, true, false, false); + new UidlWriter().write(uI, writer, true, false); writer.write("}"); String initialUIDL = writer.toString(); diff --git a/server/src/com/vaadin/server/communication/UidlRequestHandler.java b/server/src/com/vaadin/server/communication/UidlRequestHandler.java index 73ff92f8bd..3564aa65b5 100644 --- a/server/src/com/vaadin/server/communication/UidlRequestHandler.java +++ b/server/src/com/vaadin/server/communication/UidlRequestHandler.java @@ -19,13 +19,11 @@ package com.vaadin.server.communication; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; -import java.util.LinkedList; import java.util.logging.Level; import java.util.logging.Logger; import org.json.JSONException; -import com.vaadin.server.ClientConnector; import com.vaadin.server.Constants; import com.vaadin.server.LegacyCommunicationManager.InvalidUIDLSecurityKeyException; import com.vaadin.server.ServletPortletHelper; @@ -39,7 +37,6 @@ import com.vaadin.server.VaadinSession; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.JsonConstants; import com.vaadin.shared.Version; -import com.vaadin.ui.Component; import com.vaadin.ui.UI; /** @@ -79,32 +76,16 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements checkWidgetsetVersion(request); String requestThemeName = request.getParameter("theme"); - ClientConnector highlightedConnector; // repaint requested or session has timed out and new one is created boolean repaintAll; - // TODO PUSH repaintAll, analyzeLayouts, highlightConnector should be + // TODO PUSH repaintAll, analyzeLayouts should be // part of the message payload to make the functionality transport // agnostic repaintAll = (request .getParameter(ApplicationConstants.URL_PARAMETER_REPAINT_ALL) != null); - boolean analyzeLayouts = false; - if (repaintAll) { - // analyzing can be done only with repaintAll - analyzeLayouts = (request - .getParameter(ApplicationConstants.PARAM_ANALYZE_LAYOUTS) != null); - - String pid = request - .getParameter(ApplicationConstants.PARAM_HIGHLIGHT_CONNECTOR); - if (pid != null) { - highlightedConnector = uI.getConnectorTracker().getConnector( - pid); - highlightConnector(highlightedConnector); - } - } - StringWriter stringWriter = new StringWriter(); try { @@ -114,8 +95,7 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements session.getCommunicationManager().repaintAll(uI); } - writeUidl(request, response, uI, stringWriter, repaintAll, - analyzeLayouts); + writeUidl(request, response, uI, stringWriter, repaintAll); } catch (JSONException e) { getLogger().log(Level.SEVERE, "Error writing JSON to response", e); // Refresh on client side @@ -164,11 +144,11 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements } private void writeUidl(VaadinRequest request, VaadinResponse response, - UI ui, Writer writer, boolean repaintAll, boolean analyzeLayouts) - throws IOException, JSONException { + UI ui, Writer writer, boolean repaintAll) throws IOException, + JSONException { openJsonMessage(writer, response); - new UidlWriter().write(ui, writer, repaintAll, analyzeLayouts, false); + new UidlWriter().write(ui, writer, repaintAll, false); closeJsonMessage(writer); } @@ -190,63 +170,6 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements outWriter.write("for(;;);[{"); } - // TODO Does this belong here? - protected void highlightConnector(ClientConnector highlightedConnector) { - StringBuilder sb = new StringBuilder(); - sb.append("*** Debug details of a connector: *** \n"); - sb.append("Type: "); - sb.append(highlightedConnector.getClass().getName()); - sb.append("\nId:"); - sb.append(highlightedConnector.getConnectorId()); - if (highlightedConnector instanceof Component) { - Component component = (Component) highlightedConnector; - if (component.getCaption() != null) { - sb.append("\nCaption:"); - sb.append(component.getCaption()); - } - } - printHighlightedConnectorHierarchy(sb, highlightedConnector); - getLogger().info(sb.toString()); - } - - // TODO Does this belong here? - protected void printHighlightedConnectorHierarchy(StringBuilder sb, - ClientConnector connector) { - LinkedList<ClientConnector> h = new LinkedList<ClientConnector>(); - h.add(connector); - ClientConnector parent = connector.getParent(); - while (parent != null) { - h.addFirst(parent); - parent = parent.getParent(); - } - - sb.append("\nConnector hierarchy:\n"); - VaadinSession session2 = connector.getUI().getSession(); - sb.append(session2.getClass().getName()); - sb.append("("); - sb.append(session2.getClass().getSimpleName()); - sb.append(".java"); - sb.append(":1)"); - int l = 1; - for (ClientConnector connector2 : h) { - sb.append("\n"); - for (int i = 0; i < l; i++) { - sb.append(" "); - } - l++; - Class<? extends ClientConnector> connectorClass = connector2 - .getClass(); - Class<?> topClass = connectorClass; - while (topClass.getEnclosingClass() != null) { - topClass = topClass.getEnclosingClass(); - } - sb.append(connectorClass.getName()); - sb.append("("); - sb.append(topClass.getSimpleName()); - sb.append(".java:1)"); - } - } - private static final Logger getLogger() { return Logger.getLogger(UidlRequestHandler.class.getName()); } diff --git a/server/src/com/vaadin/server/communication/UidlWriter.java b/server/src/com/vaadin/server/communication/UidlWriter.java index fbe2fb86d5..60933a75c2 100644 --- a/server/src/com/vaadin/server/communication/UidlWriter.java +++ b/server/src/com/vaadin/server/communication/UidlWriter.java @@ -71,12 +71,16 @@ public class UidlWriter implements Serializable { * @throws JSONException * If the JSON serialization fails. */ - public void write(UI ui, Writer writer, boolean repaintAll, - boolean analyzeLayouts, boolean async) throws IOException, - JSONException { + public void write(UI ui, Writer writer, boolean repaintAll, boolean async) + throws IOException, JSONException { + VaadinSession session = ui.getSession(); + + // Purge pending access calls as they might produce additional changes + // to write out + session.getService().runPendingAccessTasks(session); + ArrayList<ClientConnector> dirtyVisibleConnectors = ui .getConnectorTracker().getDirtyVisibleConnectors(); - VaadinSession session = ui.getSession(); LegacyCommunicationManager manager = session.getCommunicationManager(); // Paints components ConnectorTracker uiConnectorTracker = ui.getConnectorTracker(); @@ -156,8 +160,7 @@ public class UidlWriter implements Serializable { SystemMessages messages = ui.getSession().getService() .getSystemMessages(ui.getLocale(), null); // TODO hilightedConnector - new MetadataWriter().write(ui, writer, repaintAll, analyzeLayouts, - async, null, messages); + new MetadataWriter().write(ui, writer, repaintAll, async, messages); writer.write(", "); writer.write("\"resources\" : "); @@ -278,10 +281,6 @@ public class UidlWriter implements Serializable { + new JSONArray(styleDependencies).toString()); } - // add any pending locale definitions requested by the client - writer.write(", \"locales\": "); - manager.printLocaleDeclarations(writer); - if (manager.getDragAndDropService() != null) { manager.getDragAndDropService().printJSONResponse(writer); } diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java index 06060dbf91..9ff36a42d2 100644 --- a/server/src/com/vaadin/ui/AbstractComponent.java +++ b/server/src/com/vaadin/ui/AbstractComponent.java @@ -291,7 +291,10 @@ public abstract class AbstractComponent extends AbstractClientConnector public void setLocale(Locale locale) { this.locale = locale; - // FIXME: Reload value if there is a converter + if (locale != null && isAttached()) { + getUI().getLocaleService().addLocale(locale); + } + markAsDirty(); } @@ -556,6 +559,10 @@ public abstract class AbstractComponent extends AbstractClientConnector focus(); } setActionManagerViewer(); + if (locale != null) { + getUI().getLocaleService().addLocale(locale); + } + } /* diff --git a/server/src/com/vaadin/ui/AbstractField.java b/server/src/com/vaadin/ui/AbstractField.java index 3bca63a3b7..606bf5fb21 100644 --- a/server/src/com/vaadin/ui/AbstractField.java +++ b/server/src/com/vaadin/ui/AbstractField.java @@ -616,17 +616,14 @@ public abstract class AbstractField<T> extends AbstractComponent implements // Check if the current converter is compatible. if (newDataSource != null - && !ConverterUtil.canConverterHandle(getConverter(), getType(), - newDataSource.getType())) { - // Changing from e.g. Number -> Double should set a new converter, - // changing from Double -> Number can keep the old one (Property - // accepts Number) - - // Set a new converter if there is a new data source and - // there is no old converter or the old is incompatible. + && !ConverterUtil.canConverterPossiblyHandle(getConverter(), + getType(), newDataSource.getType())) { + // There is no converter set or there is no way the current + // converter can be compatible. setConverter(newDataSource.getType()); } - // Gets the value from source + // Gets the value from source. This requires that a valid converter has + // been set. try { if (dataSource != null) { T fieldValue = convertFromModel(getDataSourceValue()); diff --git a/server/src/com/vaadin/ui/Calendar.java b/server/src/com/vaadin/ui/Calendar.java index 38fa355dd8..c3385baa2c 100644 --- a/server/src/com/vaadin/ui/Calendar.java +++ b/server/src/com/vaadin/ui/Calendar.java @@ -45,6 +45,8 @@ import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.DropTarget; import com.vaadin.event.dd.TargetDetails; import com.vaadin.server.KeyMapper; +import com.vaadin.server.PaintException; +import com.vaadin.server.PaintTarget; import com.vaadin.shared.ui.calendar.CalendarEventId; import com.vaadin.shared.ui.calendar.CalendarServerRpc; import com.vaadin.shared.ui.calendar.CalendarState; @@ -114,7 +116,7 @@ public class Calendar extends AbstractComponent implements CalendarComponentEvents.RangeSelectNotifier, CalendarComponentEvents.EventResizeNotifier, CalendarEventProvider.EventSetChangeListener, DropTarget, - CalendarEditableEventProvider, Action.Container { + CalendarEditableEventProvider, Action.Container, LegacyComponent { /** * Calendar can use either 12 hours clock or 24 hours clock. @@ -1842,4 +1844,31 @@ public class Calendar extends AbstractComponent implements } } } + + /* + * (non-Javadoc) + * + * @see com.vaadin.server.VariableOwner#changeVariables(java.lang.Object, + * java.util.Map) + */ + @Override + public void changeVariables(Object source, Map<String, Object> variables) { + /* + * Only defined to fulfill the LegacyComponent interface used for + * calendar drag & drop. No implementation required. + */ + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.ui.LegacyComponent#paintContent(com.vaadin.server.PaintTarget) + */ + @Override + public void paintContent(PaintTarget target) throws PaintException { + if (dropHandler != null) { + dropHandler.getAcceptCriterion().paint(target); + } + } }
\ No newline at end of file diff --git a/server/src/com/vaadin/ui/Label.java b/server/src/com/vaadin/ui/Label.java index d037652a09..d7cee2a80d 100644 --- a/server/src/com/vaadin/ui/Label.java +++ b/server/src/com/vaadin/ui/Label.java @@ -242,14 +242,17 @@ public class Label extends AbstractComponent implements Property<String>, ((Property.ValueChangeNotifier) dataSource).removeListener(this); } + // Check if the current converter is compatible. if (newDataSource != null - && !ConverterUtil.canConverterHandle(getConverter(), - String.class, newDataSource.getType())) { - // Try to find a converter + && !ConverterUtil.canConverterPossiblyHandle(getConverter(), + getType(), newDataSource.getType())) { + // There is no converter set or there is no way the current + // converter can be compatible. Converter<String, ?> c = ConverterUtil.getConverter(String.class, newDataSource.getType(), getSession()); setConverter(c); } + dataSource = newDataSource; if (dataSource != null) { // Update the value from the data source. If data source was set to diff --git a/server/src/com/vaadin/ui/LegacyWindow.java b/server/src/com/vaadin/ui/LegacyWindow.java index 1b66b608c1..458b09390d 100644 --- a/server/src/com/vaadin/ui/LegacyWindow.java +++ b/server/src/com/vaadin/ui/LegacyWindow.java @@ -125,7 +125,7 @@ public class LegacyWindow extends UI { public void setName(String name) { this.name = name; // The name can not be changed in application - if (getSession() != null) { + if (isAttached()) { throw new IllegalStateException( "Window name can not be changed while " + "the window is in application"); diff --git a/server/src/com/vaadin/ui/LoginForm.java b/server/src/com/vaadin/ui/LoginForm.java index d06882927e..67d7182ecb 100644 --- a/server/src/com/vaadin/ui/LoginForm.java +++ b/server/src/com/vaadin/ui/LoginForm.java @@ -68,7 +68,7 @@ public class LoginForm extends CustomComponent { } final StringBuilder responseBuilder = new StringBuilder(); - getUI().access(new Runnable() { + getUI().accessSynchronously(new Runnable() { @Override public void run() { String method = VaadinServletService.getCurrentServletRequest() diff --git a/server/src/com/vaadin/ui/ProgressBar.java b/server/src/com/vaadin/ui/ProgressBar.java new file mode 100644 index 0000000000..3f8aab6d7c --- /dev/null +++ b/server/src/com/vaadin/ui/ProgressBar.java @@ -0,0 +1,152 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.ui; + +import com.vaadin.data.Property; +import com.vaadin.shared.ui.progressindicator.ProgressBarState; + +/** + * Shows the current progress of a long running task. + * <p> + * The default mode is to show the current progress internally represented by a + * floating point value between 0 and 1 (inclusive). The progress bar can also + * be in an indeterminate mode showing an animation indicating that the task is + * running but without providing any information about the current progress. + * + * @since 7.1 + * @author Vaadin Ltd + */ +public class ProgressBar extends AbstractField<Float> implements + Property.Viewer, Property.ValueChangeListener { + + /** + * Creates a new progress bar initially set to 0% progress. + */ + public ProgressBar() { + this(0); + } + + /** + * Creates a new progress bar with the given initial value. + * + * @param progress + * the initial progress value + */ + public ProgressBar(float progress) { + setValue(Float.valueOf(progress)); + } + + /** + * Creates a new progress bar bound to the given data source. + * + * @param dataSource + * the property to bind this progress bar to + */ + public ProgressBar(Property<?> dataSource) { + setPropertyDataSource(dataSource); + } + + @Override + public void beforeClientResponse(boolean initial) { + super.beforeClientResponse(initial); + + // Update value in state even if the property hasn't fired any event + getState().state = getValue(); + } + + /** + * Gets the value of this progress bar. The value is a <code>float</code> + * between 0 and 1 where 0 represents no progress at all and 1 represents + * fully completed. + * + * @return the current progress value + */ + @Override + public Float getValue() { + return super.getValue(); + } + + /** + * Sets the value of this progress bar. The value is a <code>float</code> + * between 0 and 1 where 0 represents no progress at all and 1 represents + * fully completed. + * + * @param newValue + * the current progress value + */ + @Override + public void setValue(Float newValue) { + super.setValue(newValue); + } + + @Override + public Class<Float> getType() { + return Float.class; + } + + @Override + protected ProgressBarState getState() { + return (ProgressBarState) super.getState(); + } + + @Override + protected ProgressBarState getState(boolean markAsDirty) { + return (ProgressBarState) super.getState(markAsDirty); + } + + /** + * Sets whether or not this progress indicator is indeterminate. In + * indeterminate mode there is an animation indicating that the task is + * running but without providing any information about the current progress. + * + * @param indeterminate + * <code>true</code> to set to indeterminate mode; otherwise + * <code>false</code> + */ + public void setIndeterminate(boolean indeterminate) { + getState().indeterminate = indeterminate; + } + + /** + * Gets whether or not this progress indicator is indeterminate. In + * indeterminate mode there is an animation indicating that the task is + * running but without providing any information about the current progress. + * + * @return <code>true</code> if set to indeterminate mode; otherwise + * <code>false</code> + */ + public boolean isIndeterminate() { + return getState(false).indeterminate; + } + + /* + * Overridden to keep the shared state in sync with the AbstractField + * internal value. Should be removed once AbstractField is refactored to use + * shared state. + * + * See tickets #10921 and #11064. + */ + @Override + protected void setInternalValue(Float newValue) { + super.setInternalValue(newValue); + if (newValue == null) { + newValue = Float.valueOf(0); + } + getState().state = newValue; + } + +}
\ No newline at end of file diff --git a/server/src/com/vaadin/ui/ProgressIndicator.java b/server/src/com/vaadin/ui/ProgressIndicator.java index c481aa1e8f..6da18fc29d 100644 --- a/server/src/com/vaadin/ui/ProgressIndicator.java +++ b/server/src/com/vaadin/ui/ProgressIndicator.java @@ -17,24 +17,27 @@ package com.vaadin.ui; import com.vaadin.data.Property; +import com.vaadin.shared.communication.PushMode; import com.vaadin.shared.ui.progressindicator.ProgressIndicatorServerRpc; import com.vaadin.shared.ui.progressindicator.ProgressIndicatorState; /** - * <code>ProgressIndicator</code> is component that shows user state of a - * process (like long computing or file upload) - * - * <code>ProgressIndicator</code> has two main modes. One for indeterminate - * processes and other (default) for processes which progress can be measured - * - * May view an other property that indicates progress 0...1 + * A {@link ProgressBar} which polls the server for updates. + * <p> + * Polling in this way is generally not recommended since there is no + * centralized management of when messages are sent to the server. Furthermore, + * polling might not be needed at all if {@link UI#setPushMode(PushMode)} or + * {@link UI#setPollInterval(int)} is used. * * @author Vaadin Ltd. * @since 4 + * @deprecated as of 7.1, use {@link ProgressBar} combined with + * {@link UI#setPushMode(PushMode)} or + * {@link UI#setPollInterval(int)} instead. */ +@Deprecated @SuppressWarnings("serial") -public class ProgressIndicator extends AbstractField<Float> implements - Property.Viewer, Property.ValueChangeListener { +public class ProgressIndicator extends ProgressBar { private ProgressIndicatorServerRpc rpc = new ProgressIndicatorServerRpc() { @@ -57,7 +60,7 @@ public class ProgressIndicator extends AbstractField<Float> implements * @param value */ public ProgressIndicator(float value) { - setValue(value); + super(value); registerRpc(rpc); } @@ -68,74 +71,18 @@ public class ProgressIndicator extends AbstractField<Float> implements * @param contentSource */ public ProgressIndicator(Property contentSource) { - setPropertyDataSource(contentSource); + super(contentSource); registerRpc(rpc); } @Override - public void beforeClientResponse(boolean initial) { - super.beforeClientResponse(initial); - - getState().state = getValue(); - } - - /** - * Gets the value of the ProgressIndicator. Value of the ProgressIndicator - * is Float between 0 and 1. - * - * @return the Value of the ProgressIndicator. - * @see com.vaadin.ui.AbstractField#getValue() - */ - @Override - public Float getValue() { - return super.getValue(); - } - - /** - * Sets the value of the ProgressIndicator. Value of the ProgressIndicator - * is the Float between 0 and 1. - * - * @param newValue - * the New value of the ProgressIndicator. - * @see com.vaadin.ui.AbstractField#setValue() - */ - @Override - public void setValue(Float newValue) { - super.setValue(newValue); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.AbstractField#getType() - */ - @Override - public Class<Float> getType() { - return Float.class; - } - - @Override protected ProgressIndicatorState getState() { return (ProgressIndicatorState) super.getState(); } - /** - * Sets whether or not the ProgressIndicator is indeterminate. - * - * @param indeterminate - * true to set to indeterminate mode. - */ - public void setIndeterminate(boolean indeterminate) { - getState().indeterminate = indeterminate; - } - - /** - * Gets whether or not the ProgressIndicator is indeterminate. - * - * @return true to set to indeterminate mode. - */ - public boolean isIndeterminate() { - return getState().indeterminate; + @Override + protected ProgressIndicatorState getState(boolean markAsDirty) { + return (ProgressIndicatorState) super.getState(markAsDirty); } /** @@ -154,22 +101,6 @@ public class ProgressIndicator extends AbstractField<Float> implements * @return the interval in milliseconds. */ public int getPollingInterval() { - return getState().pollingInterval; - } - - /* - * Overridden to keep the shared state in sync with the AbstractField - * internal value. Should be removed once AbstractField is refactored to use - * shared state. - * - * See tickets #10921 and #11064. - */ - @Override - protected void setInternalValue(Float newValue) { - super.setInternalValue(newValue); - if (newValue == null) { - newValue = 0.0f; - } - getState().state = newValue; + return getState(false).pollingInterval; } } diff --git a/server/src/com/vaadin/ui/PushConfiguration.java b/server/src/com/vaadin/ui/PushConfiguration.java new file mode 100644 index 0000000000..a592b39bef --- /dev/null +++ b/server/src/com/vaadin/ui/PushConfiguration.java @@ -0,0 +1,282 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.ui; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; + +import com.vaadin.server.VaadinSession; +import com.vaadin.shared.communication.PushMode; +import com.vaadin.shared.ui.ui.Transport; +import com.vaadin.shared.ui.ui.UIState.PushConfigurationState; + +/** + * Provides method for configuring the push channel. + * + * @since 7.1 + * @author Vaadin Ltd + */ +public interface PushConfiguration extends Serializable { + + /** + * Returns the mode of bidirectional ("push") communication that is used. + * + * @return The push mode. + */ + public PushMode getPushMode(); + + /** + * Sets the mode of bidirectional ("push") communication that should be + * used. + * <p> + * Add-on developers should note that this method is only meant for the + * application developer. An add-on should not set the push mode directly, + * rather instruct the user to set it. + * </p> + * + * @param pushMode + * The push mode to use. + * + * @throws IllegalArgumentException + * if the argument is null. + * @throws IllegalStateException + * if push support is not available. + */ + public void setPushMode(PushMode pushMode); + + /** + * Returns the primary transport type for push. + * <p> + * Note that if you set the transport type using + * {@link #setParameter(String, String)} to an unsupported type this method + * will return null. Supported types are defined by {@link Transport}. + * + * @return The primary transport type + */ + public Transport getTransport(); + + /** + * Sets the primary transport type for push. + * <p> + * Note that the new transport type will not be used until the push channel + * is disconnected and reconnected if already active. + * + * @param transport + * The primary transport type + */ + public void setTransport(Transport transport); + + /** + * Returns the fallback transport type for push. + * <p> + * Note that if you set the transport type using + * {@link #setParameter(String, String)} to an unsupported type this method + * will return null. Supported types are defined by {@link Transport}. + * + * @return The fallback transport type + */ + public Transport getFallbackTransport(); + + /** + * Sets the fallback transport type for push. + * <p> + * Note that the new transport type will not be used until the push channel + * is disconnected and reconnected if already active. + * + * @param fallbackTransport + * The fallback transport type + */ + public void setFallbackTransport(Transport fallbackTransport); + + /** + * Returns the given parameter, if set. + * <p> + * This method provides low level access to push parameters and is typically + * not needed for normal application development. + * + * @since 7.1 + * @param parameter + * The parameter name + * @return The parameter value or null if not set + */ + public String getParameter(String parameter); + + /** + * Returns the parameters which have been defined. + * + * @since 7.1 + * @return A collection of parameter names + */ + public Collection<String> getParameterNames(); + + /** + * Sets the given parameter. + * <p> + * This method provides low level access to push parameters and is typically + * not needed for normal application development. + * + * @since 7.1 + * @param parameter + * The parameter name + * @param value + * The value + */ + public void setParameter(String parameter, String value); + +} + +class PushConfigurationImpl implements PushConfiguration { + private UI ui; + + public PushConfigurationImpl(UI ui) { + this.ui = ui; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.PushConfiguration#getPushMode() + */ + @Override + public PushMode getPushMode() { + return getState(false).mode; + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.ui.PushConfiguration#setPushMode(com.vaadin.shared.communication + * .PushMode) + */ + @Override + public void setPushMode(PushMode pushMode) { + if (pushMode == null) { + throw new IllegalArgumentException("Push mode cannot be null"); + } + + if (pushMode.isEnabled()) { + VaadinSession session = ui.getSession(); + if (session != null && !session.getService().ensurePushAvailable()) { + throw new IllegalStateException( + "Push is not available. See previous log messages for more information."); + } + } + + /* + * Client-side will open a new connection or disconnect the old + * connection, so there's nothing more to do on the server at this + * point. + */ + getState().mode = pushMode; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.PushConfiguration#getTransport() + */ + @Override + public Transport getTransport() { + try { + return Transport + .valueOf(getParameter(PushConfigurationState.TRANSPORT_PARAM)); + } catch (IllegalArgumentException e) { + return null; + } + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.ui.PushConfiguration#setTransport(com.vaadin.shared.ui.ui. + * Transport) + */ + @Override + public void setTransport(Transport transport) { + setParameter(PushConfigurationState.TRANSPORT_PARAM, + transport.getIdentifier()); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.PushConfiguration#getFallbackTransport() + */ + @Override + public Transport getFallbackTransport() { + try { + return Transport + .valueOf(getParameter(PushConfigurationState.FALLBACK_TRANSPORT_PARAM)); + } catch (IllegalArgumentException e) { + return null; + } + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.ui.PushConfiguration#setFallbackTransport(com.vaadin.shared + * .ui.ui.Transport) + */ + @Override + public void setFallbackTransport(Transport fallbackTransport) { + setParameter(PushConfigurationState.FALLBACK_TRANSPORT_PARAM, + fallbackTransport.getIdentifier()); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.PushConfiguration#getParameter(java.lang.String) + */ + @Override + public String getParameter(String parameter) { + return getState(false).parameters.get(parameter); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.PushConfiguration#setParameter(java.lang.String, + * java.lang.String) + */ + @Override + public void setParameter(String parameter, String value) { + getState().parameters.put(parameter, value); + + } + + private PushConfigurationState getState() { + return ui.getState().pushConfiguration; + } + + private PushConfigurationState getState(boolean markAsDirty) { + return ui.getState(markAsDirty).pushConfiguration; + } + + @Override + public Collection<String> getParameterNames() { + return Collections + .unmodifiableCollection(ui.getState(false).pushConfiguration.parameters + .keySet()); + } + +} diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java index 0a4ed7c491..9135151089 100644 --- a/server/src/com/vaadin/ui/UI.java +++ b/server/src/com/vaadin/ui/UI.java @@ -21,7 +21,10 @@ import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; +import java.util.concurrent.Future; +import java.util.logging.Logger; import com.vaadin.event.Action; import com.vaadin.event.Action.Handler; @@ -29,6 +32,10 @@ import com.vaadin.event.ActionManager; import com.vaadin.event.MouseEvents.ClickEvent; import com.vaadin.event.MouseEvents.ClickListener; import com.vaadin.navigator.Navigator; +import com.vaadin.server.ClientConnector; +import com.vaadin.server.ComponentSizeValidator; +import com.vaadin.server.ComponentSizeValidator.InvalidLayout; +import com.vaadin.server.LocaleService; import com.vaadin.server.Page; import com.vaadin.server.PaintException; import com.vaadin.server.PaintTarget; @@ -38,15 +45,18 @@ import com.vaadin.server.VaadinService; import com.vaadin.server.VaadinServlet; import com.vaadin.server.VaadinSession; import com.vaadin.server.communication.PushConnection; +import com.vaadin.shared.Connector; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.communication.PushMode; +import com.vaadin.shared.ui.ui.DebugWindowClientRpc; +import com.vaadin.shared.ui.ui.DebugWindowServerRpc; import com.vaadin.shared.ui.ui.ScrollClientRpc; import com.vaadin.shared.ui.ui.UIClientRpc; import com.vaadin.shared.ui.ui.UIConstants; import com.vaadin.shared.ui.ui.UIServerRpc; import com.vaadin.shared.ui.ui.UIState; import com.vaadin.ui.Component.Focusable; +import com.vaadin.util.ConnectorHelper; import com.vaadin.util.CurrentInstance; /** @@ -86,7 +96,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements /** * The application to which this UI belongs */ - private VaadinSession session; + private volatile VaadinSession session; /** * List of windows in this UI. @@ -159,6 +169,40 @@ public abstract class UI extends AbstractSingleComponentContainer implements */ } }; + private DebugWindowServerRpc debugRpc = new DebugWindowServerRpc() { + @Override + public void showServerDebugInfo(Connector connector) { + String info = ConnectorHelper + .getDebugInformation((ClientConnector) connector); + getLogger().info(info); + } + + @Override + public void analyzeLayouts() { + // TODO Move to client side + List<InvalidLayout> invalidSizes = ComponentSizeValidator + .validateLayouts(UI.this); + StringBuilder json = new StringBuilder(); + json.append("{\"invalidLayouts\":"); + json.append("["); + + if (invalidSizes != null) { + boolean first = true; + for (InvalidLayout invalidSize : invalidSizes) { + if (!first) { + json.append(","); + } else { + first = false; + } + invalidSize.reportErrors(json, System.err); + } + } + json.append("]}"); + getRpcProxy(DebugWindowClientRpc.class).reportLayoutProblems( + json.toString()); + } + + }; /** * Timestamp keeping track of the last heartbeat of this UI. Updated to the @@ -171,6 +215,8 @@ public abstract class UI extends AbstractSingleComponentContainer implements private TooltipConfiguration tooltipConfiguration = new TooltipConfigurationImpl( this); + private PushConfiguration pushConfiguration = new PushConfigurationImpl( + this); /** * Creates a new empty UI without a caption. The content of the UI must be @@ -191,6 +237,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements */ public UI(Component content) { registerRpc(rpc); + registerRpc(debugRpc); setSizeFull(); setContent(content); } @@ -418,7 +465,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements throw new NullPointerException("Argument must not be null"); } - if (window.getUI() != null && window.getUI().getSession() != null) { + if (window.isAttached()) { throw new IllegalArgumentException( "Window is already attached to an application."); } @@ -493,6 +540,9 @@ public abstract class UI extends AbstractSingleComponentContainer implements private boolean hasPendingPush = false; + private LocaleService localeService = new LocaleService(this, + getState(false).localeServiceState); + /** * This method is used by Component.Focusable objects to request focus to * themselves. Focus renders must be handled at window level (instead of @@ -1051,6 +1101,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements @Override public void attach() { super.attach(); + getLocaleService().addLocale(getLocale()); } /** @@ -1098,24 +1149,30 @@ public abstract class UI extends AbstractSingleComponentContainer implements } /** - * Provides exclusive access to this UI from outside a request handling - * thread. - * <p> - * The given runnable is executed while holding the session lock to ensure - * exclusive access to this UI and its session. The UI and related thread - * locals are set properly before executing the runnable. - * </p> + * Locks the session of this UI and runs the provided Runnable right away. * <p> - * RPC handlers for components inside this UI do not need this method as the - * session is automatically locked by the framework during request handling. + * It is generally recommended to use {@link #access(Runnable)} instead of + * this method for accessing a session from a different thread as + * {@link #access(Runnable)} can be used while holding the lock of another + * session. To avoid causing deadlocks, this methods throws an exception if + * it is detected than another session is also locked by the current thread. * </p> * <p> - * Note that calling this method while another session is locked by the - * current thread will cause an exception. This is to prevent deadlock - * situations when two threads have locked one session each and are both - * waiting for the lock for the other session. + * This method behaves differently than {@link #access(Runnable)} in some + * situations: + * <ul> + * <li>If the current thread is currently holding the lock of the session, + * {@link #accessSynchronously(Runnable)} runs the task right away whereas + * {@link #access(Runnable)} defers the task to a later point in time.</li> + * <li>If some other thread is currently holding the lock for the session, + * {@link #accessSynchronously(Runnable)} blocks while waiting for the lock + * to be available whereas {@link #access(Runnable)} defers the task to a + * later point in time.</li> + * </ul> * </p> * + * @since 7.1 + * * @param runnable * the runnable which accesses the UI * @throws UIDetachedException @@ -1124,11 +1181,11 @@ public abstract class UI extends AbstractSingleComponentContainer implements * @throws IllegalStateException * if the current thread holds the lock for another session * - * @see #getCurrent() - * @see VaadinSession#access(Runnable) - * @see VaadinSession#lock() + * @see #access(Runnable) + * @see VaadinSession#accessSynchronously(Runnable) */ - public void access(Runnable runnable) throws UIDetachedException { + public void accessSynchronously(Runnable runnable) + throws UIDetachedException { Map<Class<?>, CurrentInstance> old = null; VaadinSession session = getSession(); @@ -1146,24 +1203,76 @@ public abstract class UI extends AbstractSingleComponentContainer implements // acquired the lock. throw new UIDetachedException(); } - old = CurrentInstance.setThreadLocals(this); + old = CurrentInstance.setCurrent(this); runnable.run(); } finally { session.unlock(); if (old != null) { - CurrentInstance.restoreThreadLocals(old); + CurrentInstance.restoreInstances(old); } } } /** - * @deprecated As of 7.1.0.beta1, use {@link #access(Runnable)} instead. - * This method will be removed before the final 7.1.0 release. + * Provides exclusive access to this UI from outside a request handling + * thread. + * <p> + * The given runnable is executed while holding the session lock to ensure + * exclusive access to this UI. If the session is not locked, the lock will + * be acquired and the runnable is run right away. If the session is + * currently locked, the runnable will be run before that lock is released. + * </p> + * <p> + * RPC handlers for components inside this UI do not need to use this method + * as the session is automatically locked by the framework during RPC + * handling. + * </p> + * <p> + * Please note that the runnable might be invoked on a different thread or + * later on the current thread, which means that custom thread locals might + * not have the expected values when the runnable is executed. Inheritable + * values in {@link CurrentInstance} will have the same values as when this + * method was invoked. {@link UI#getCurrent()}, + * {@link VaadinSession#getCurrent()} and {@link VaadinService#getCurrent()} + * are set according to this UI before executing the runnable. + * Non-inheritable CurrentInstance values including + * {@link VaadinService#getCurrentRequest()} and + * {@link VaadinService#getCurrentResponse()} will not be defined. + * </p> + * <p> + * The returned future can be used to check for task completion and to + * cancel the task. + * </p> + * + * @see #getCurrent() + * @see #accessSynchronously(Runnable) + * @see VaadinSession#access(Runnable) + * @see VaadinSession#lock() + * + * @since 7.1 + * + * @param runnable + * the runnable which accesses the UI + * @throws UIDetachedException + * if the UI is not attached to a session (and locking can + * therefore not be done) + * @return a future that can be used to check for task completion and to + * cancel the task */ - @Deprecated - public void runSafely(Runnable runnable) throws UIDetachedException { - access(runnable); + public Future<Void> access(final Runnable runnable) { + VaadinSession session = getSession(); + + if (session == null) { + throw new UIDetachedException(); + } + + return session.access(new Runnable() { + @Override + public void run() { + accessSynchronously(runnable); + } + }); } /** @@ -1204,12 +1313,20 @@ public abstract class UI extends AbstractSingleComponentContainer implements VaadinSession session = getSession(); if (session != null) { assert session.hasLock(); + + /* + * Purge the pending access queue as it might mark a connector as + * dirty when the push would otherwise be ignored because there are + * no changes to push. + */ + session.getService().runPendingAccessTasks(session); + if (!getConnectorTracker().hasDirtyConnectors()) { // Do not push if there is nothing to push return; } - if (!getPushMode().isEnabled()) { + if (!getPushConfiguration().getPushMode().isEnabled()) { throw new IllegalStateException("Push not enabled"); } @@ -1237,7 +1354,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements */ public void setPushConnection(PushConnection pushConnection) { // If pushMode is disabled then there should never be a pushConnection - assert (getPushMode().isEnabled() || pushConnection == null); + assert (getPushConfiguration().getPushMode().isEnabled() || pushConnection == null); if (pushConnection == this.pushConnection) { return; @@ -1286,51 +1403,13 @@ public abstract class UI extends AbstractSingleComponentContainer implements } /** - * Returns the mode of bidirectional ("push") communication that is used in - * this UI. - * - * @return The push mode. - */ - public PushMode getPushMode() { - return getState(false).pushMode; - } - - /** - * Sets the mode of bidirectional ("push") communication that should be used - * in this UI. - * <p> - * Add-on developers should note that this method is only meant for the - * application developer. An add-on should not set the push mode directly, - * rather instruct the user to set it. - * </p> - * - * @param pushMode - * The push mode to use. + * Retrieves the object used for configuring the push channel. * - * @throws IllegalArgumentException - * if the argument is null. - * @throws IllegalStateException - * if push support is not available. + * @since 7.1 + * @return The instance used for push configuration */ - public void setPushMode(PushMode pushMode) { - if (pushMode == null) { - throw new IllegalArgumentException("Push mode cannot be null"); - } - - if (pushMode.isEnabled()) { - VaadinSession session = getSession(); - if (session != null && !session.getService().ensurePushAvailable()) { - throw new IllegalStateException( - "Push is not available. See previous log messages for more information."); - } - } - - /* - * Client-side will open a new connection or disconnect the old - * connection, so there's nothing more to do on the server at this - * point. - */ - getState().pushMode = pushMode; + public PushConfiguration getPushConfiguration() { + return pushConfiguration; } /** @@ -1357,4 +1436,19 @@ public abstract class UI extends AbstractSingleComponentContainer implements public void setOverlayContainerLabel(String overlayContainerLabel) { getState().overlayContainerLabel = overlayContainerLabel; } + + /** + * Returns the locale service which handles transmission of Locale data to + * the client. + * + * @since 7.1 + * @return The LocaleService for this UI + */ + public LocaleService getLocaleService() { + return localeService; + } + + private static Logger getLogger() { + return Logger.getLogger(UI.class.getName()); + } } diff --git a/server/src/com/vaadin/ui/components/colorpicker/ColorPickerHistory.java b/server/src/com/vaadin/ui/components/colorpicker/ColorPickerHistory.java index 2902585f56..de8c5db195 100644 --- a/server/src/com/vaadin/ui/components/colorpicker/ColorPickerHistory.java +++ b/server/src/com/vaadin/ui/components/colorpicker/ColorPickerHistory.java @@ -95,7 +95,7 @@ public class ColorPickerHistory extends CustomComponent implements @SuppressWarnings("unchecked") private ArrayBlockingQueue<Color> getColorHistory() { - if (getSession() != null) { + if (isAttached()) { Object colorHistory = getSession().getAttribute( "colorPickerHistory"); if (colorHistory instanceof ArrayBlockingQueue<?>) { diff --git a/server/src/com/vaadin/util/ConnectorHelper.java b/server/src/com/vaadin/util/ConnectorHelper.java new file mode 100644 index 0000000000..e698e9222a --- /dev/null +++ b/server/src/com/vaadin/util/ConnectorHelper.java @@ -0,0 +1,101 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.util; + +import java.util.LinkedList; + +import com.vaadin.server.ClientConnector; +import com.vaadin.ui.Component; + +/** + * Provides various helper methods for connectors. Meant for internal use. + * + * @since 7.1 + * @author Vaadin Ltd + */ +public class ConnectorHelper { + + /** + * Creates a string containing debug info for the connector + * + * @since 7.1 + * @param connector + * The connector to print debug info about + * @return A string with debug information + */ + public static String getDebugInformation(ClientConnector connector) { + StringBuilder sb = new StringBuilder(); + sb.append("*** Debug details of a connector: *** \n"); + sb.append("Type: "); + sb.append(connector.getClass().getName()); + sb.append("\nId:"); + sb.append(connector.getConnectorId()); + if (connector instanceof Component) { + Component component = (Component) connector; + if (component.getCaption() != null) { + sb.append("\nCaption:"); + sb.append(component.getCaption()); + } + } + writeHierarchyInformation(connector, sb); + return sb.toString(); + } + + /** + * Creates a string containing hierarchy information for the connector + * + * @since 7.1 + * @param connector + * The connector to get hierarchy information for + * @param builder + * The StringBuilder where the information should be written + */ + public static void writeHierarchyInformation(ClientConnector connector, + StringBuilder builder) { + LinkedList<ClientConnector> h = new LinkedList<ClientConnector>(); + h.add(connector); + ClientConnector parent = connector.getParent(); + while (parent != null) { + h.addFirst(parent); + parent = parent.getParent(); + } + + builder.append("\nConnector hierarchy:\n"); + + int l = 0; + for (ClientConnector connector2 : h) { + if (l != 0) { + builder.append("\n"); + for (int i = 0; i < l; i++) { + builder.append(" "); + } + } + l++; + Class<? extends ClientConnector> connectorClass = connector2 + .getClass(); + Class<?> topClass = connectorClass; + while (topClass.getEnclosingClass() != null) { + topClass = topClass.getEnclosingClass(); + } + builder.append(connectorClass.getName()); + builder.append("("); + builder.append(topClass.getSimpleName()); + builder.append(".java:1)"); + } + } + +} diff --git a/server/src/com/vaadin/util/CurrentInstance.java b/server/src/com/vaadin/util/CurrentInstance.java index 60489d596e..b97bab3d8a 100644 --- a/server/src/com/vaadin/util/CurrentInstance.java +++ b/server/src/com/vaadin/util/CurrentInstance.java @@ -17,53 +17,41 @@ package com.vaadin.util; import java.io.Serializable; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; -import com.vaadin.server.VaadinPortlet; -import com.vaadin.server.VaadinPortletService; import com.vaadin.server.VaadinRequest; import com.vaadin.server.VaadinResponse; import com.vaadin.server.VaadinService; -import com.vaadin.server.VaadinServlet; -import com.vaadin.server.VaadinServletService; import com.vaadin.server.VaadinSession; import com.vaadin.ui.UI; /** - * Keeps track of various thread local instances used by the framework. + * Keeps track of various current instances for the current thread. All the + * instances are automatically cleared after handling a request from the client + * to avoid leaking memory. The inheritable values are also maintained when + * execution is moved to another thread, both when a new thread is created and + * when {@link VaadinSession#access(Runnable)} or {@link UI#access(Runnable)} is + * used. * <p> * Currently the framework uses the following instances: * </p> * <p> - * Inheritable: {@link UI}, {@link VaadinPortlet}, {@link VaadinService}, - * {@link VaadinServlet}, {@link VaadinSession}. + * Inheritable: {@link UI}, {@link VaadinService}, {@link VaadinSession}. * </p> * <p> * Non-inheritable: {@link VaadinRequest}, {@link VaadinResponse}. * </p> * * @author Vaadin Ltd - * @version @VERSION@ * @since 7.0.0 */ public class CurrentInstance implements Serializable { private final Object instance; private final boolean inheritable; - private static boolean portletAvailable = false; - { - try { - /* - * VaadinPortlet depends on portlet API which is available only if - * running in a portal. - */ - portletAvailable = (VaadinPortlet.class.getName() != null); - } catch (Throwable t) { - } - } - private static InheritableThreadLocal<Map<Class<?>, CurrentInstance>> instances = new InheritableThreadLocal<Map<Class<?>, CurrentInstance>>() { @Override protected Map<Class<?>, CurrentInstance> childValue( @@ -129,7 +117,9 @@ public class CurrentInstance implements Serializable { /** * Sets the current inheritable instance of the given type. A current - * instance that is inheritable will be available for child threads. + * instance that is inheritable will be available for child threads and in + * code run by {@link VaadinSession#access(Runnable)} and + * {@link UI#access(Runnable)}. * * @see #set(Class, Object) * @see InheritableThreadLocal @@ -184,13 +174,15 @@ public class CurrentInstance implements Serializable { } /** - * Restores the given thread locals to the given values. Note that this - * should only be used internally to restore Vaadin classes. + * Restores the given instances to the given values. Note that this should + * only be used internally to restore Vaadin classes. + * + * @since 7.1 * * @param old - * A Class -> Object map to set as thread locals + * A Class -> CurrentInstance map to set as current instances */ - public static void restoreThreadLocals(Map<Class<?>, CurrentInstance> old) { + public static void restoreInstances(Map<Class<?>, CurrentInstance> old) { for (Class c : old.keySet()) { CurrentInstance ci = old.get(c); set(c, ci.instance, ci.inheritable); @@ -198,30 +190,66 @@ public class CurrentInstance implements Serializable { } /** - * Sets thread locals for the UI and all related classes + * Gets the currently set instances so that they can later be restored using + * {@link #restoreInstances(Map)}. + * + * @since 7.1 + * + * @param onlyInheritable + * <code>true</code> if only the inheritable instances should be + * included; <code>false</code> to get all instances. + * @return a map containing the current instances + */ + public static Map<Class<?>, CurrentInstance> getInstances( + boolean onlyInheritable) { + Map<Class<?>, CurrentInstance> map = instances.get(); + if (map == null) { + return Collections.emptyMap(); + } else { + Map<Class<?>, CurrentInstance> copy = new HashMap<Class<?>, CurrentInstance>(); + for (Class<?> c : map.keySet()) { + CurrentInstance ci = map.get(c); + if (ci.inheritable || !onlyInheritable) { + copy.put(c, ci); + } + } + return copy; + } + } + + /** + * Sets current instances for the UI and all related classes. The previously + * defined values can be restored by passing the returned map to + * {@link #restoreInstances(Map)}. + * + * @since 7.1 * * @param ui * The UI - * @return A map containing the old values of the thread locals this method + * @return A map containing the old values of the instances that this method * updated. */ - public static Map<Class<?>, CurrentInstance> setThreadLocals(UI ui) { + public static Map<Class<?>, CurrentInstance> setCurrent(UI ui) { Map<Class<?>, CurrentInstance> old = new HashMap<Class<?>, CurrentInstance>(); old.put(UI.class, new CurrentInstance(UI.getCurrent(), true)); UI.setCurrent(ui); - old.putAll(setThreadLocals(ui.getSession())); + old.putAll(setCurrent(ui.getSession())); return old; } /** - * Sets thread locals for the {@link VaadinSession} and all related classes + * Sets current instances for the {@link VaadinSession} and all related + * classes. The previously defined values can be restored by passing the + * returned map to {@link #restoreInstances(Map)}. + * + * @since 7.1 * * @param session * The VaadinSession - * @return A map containing the old values of the thread locals this method + * @return A map containing the old values of the instances this method * updated. */ - public static Map<Class<?>, CurrentInstance> setThreadLocals( + public static Map<Class<?>, CurrentInstance> setCurrent( VaadinSession session) { Map<Class<?>, CurrentInstance> old = new HashMap<Class<?>, CurrentInstance>(); old.put(VaadinSession.class, @@ -236,18 +264,6 @@ public class CurrentInstance implements Serializable { VaadinSession.setCurrent(session); VaadinService.setCurrent(service); - if (service instanceof VaadinServletService) { - old.put(VaadinServlet.class, - new CurrentInstance(VaadinServlet.getCurrent(), true)); - VaadinServlet.setCurrent(((VaadinServletService) service) - .getServlet()); - } else if (portletAvailable && service instanceof VaadinPortletService) { - old.put(VaadinPortlet.class, - new CurrentInstance(VaadinPortlet.getCurrent(), true)); - VaadinPortlet.setCurrent(((VaadinPortletService) service) - .getPortlet()); - } - return old; } } diff --git a/server/tests/src/com/vaadin/server/MockServletConfig.java b/server/tests/src/com/vaadin/server/MockServletConfig.java new file mode 100644 index 0000000000..cd1201c249 --- /dev/null +++ b/server/tests/src/com/vaadin/server/MockServletConfig.java @@ -0,0 +1,86 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +/** + * + */ +package com.vaadin.server; + +import java.util.Enumeration; +import java.util.Properties; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; + +/** + * + * @since + * @author Vaadin Ltd + */ +public class MockServletConfig implements ServletConfig { + + private ServletContext context = new MockServletContext(); + private final Properties initParameters; + + public MockServletConfig() { + this(new Properties()); + } + + public MockServletConfig(Properties initParameters) { + this.initParameters = initParameters; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletConfig#getServletName() + */ + @Override + public String getServletName() { + return "Mock Servlet"; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletConfig#getServletContext() + */ + @Override + public ServletContext getServletContext() { + return context; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletConfig#getInitParameter(java.lang.String) + */ + @Override + public String getInitParameter(String name) { + return initParameters.getProperty(name); + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletConfig#getInitParameterNames() + */ + @Override + public Enumeration getInitParameterNames() { + return initParameters.propertyNames(); + } + +} diff --git a/server/tests/src/com/vaadin/server/MockServletContext.java b/server/tests/src/com/vaadin/server/MockServletContext.java new file mode 100644 index 0000000000..40d79190f6 --- /dev/null +++ b/server/tests/src/com/vaadin/server/MockServletContext.java @@ -0,0 +1,304 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +/** + * + */ +package com.vaadin.server; + +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Set; + +import javax.servlet.RequestDispatcher; +import javax.servlet.Servlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +/** + * + * @since + * @author Vaadin Ltd + */ +public class MockServletContext implements ServletContext { + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getContext(java.lang.String) + */ + @Override + public ServletContext getContext(String uripath) { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getMajorVersion() + */ + @Override + public int getMajorVersion() { + return 2; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getMinorVersion() + */ + @Override + public int getMinorVersion() { + return 4; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getMimeType(java.lang.String) + */ + @Override + public String getMimeType(String file) { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getResourcePaths(java.lang.String) + */ + @Override + public Set getResourcePaths(String path) { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getResource(java.lang.String) + */ + @Override + public URL getResource(String path) throws MalformedURLException { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getResourceAsStream(java.lang.String) + */ + @Override + public InputStream getResourceAsStream(String path) { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getRequestDispatcher(java.lang.String) + */ + @Override + public RequestDispatcher getRequestDispatcher(String path) { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getNamedDispatcher(java.lang.String) + */ + @Override + public RequestDispatcher getNamedDispatcher(String name) { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getServlet(java.lang.String) + */ + @Override + public Servlet getServlet(String name) throws ServletException { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getServlets() + */ + @Override + public Enumeration getServlets() { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getServletNames() + */ + @Override + public Enumeration getServletNames() { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#log(java.lang.String) + */ + @Override + public void log(String msg) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#log(java.lang.Exception, + * java.lang.String) + */ + @Override + public void log(Exception exception, String msg) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#log(java.lang.String, + * java.lang.Throwable) + */ + @Override + public void log(String message, Throwable throwable) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getRealPath(java.lang.String) + */ + @Override + public String getRealPath(String path) { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getServerInfo() + */ + @Override + public String getServerInfo() { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getInitParameter(java.lang.String) + */ + @Override + public String getInitParameter(String name) { + return null; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getInitParameterNames() + */ + @Override + public Enumeration getInitParameterNames() { + return Collections.enumeration(Collections.EMPTY_LIST); + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getAttribute(java.lang.String) + */ + @Override + public Object getAttribute(String name) { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getAttributeNames() + */ + @Override + public Enumeration getAttributeNames() { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#setAttribute(java.lang.String, + * java.lang.Object) + */ + @Override + public void setAttribute(String name, Object object) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#removeAttribute(java.lang.String) + */ + @Override + public void removeAttribute(String name) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.ServletContext#getServletContextName() + */ + @Override + public String getServletContextName() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/server/tests/src/com/vaadin/server/VaadinServletConfigurationTest.java b/server/tests/src/com/vaadin/server/VaadinServletConfigurationTest.java new file mode 100644 index 0000000000..80cb1d7b0c --- /dev/null +++ b/server/tests/src/com/vaadin/server/VaadinServletConfigurationTest.java @@ -0,0 +1,98 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +/** + * + */ +package com.vaadin.server; + +import java.util.Properties; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +import junit.framework.Assert; + +import org.easymock.EasyMock; +import org.junit.Test; + +import com.vaadin.annotations.VaadinServletConfiguration; +import com.vaadin.server.DeploymentConfiguration.LegacyProperyToStringMode; +import com.vaadin.server.VaadinServletConfigurationTest.MockUI; +import com.vaadin.ui.UI; + +public class VaadinServletConfigurationTest { + public static class MockUI extends UI { + @Override + protected void init(VaadinRequest request) { + // Do nothing + } + } + + @Test + public void testValuesFromAnnotation() throws ServletException { + TestServlet servlet = new TestServlet(); + servlet.init(new MockServletConfig()); + DeploymentConfiguration configuration = servlet.getService() + .getDeploymentConfiguration(); + + Assert.assertEquals(true, configuration.isProductionMode()); + Assert.assertEquals(LegacyProperyToStringMode.DISABLED, + configuration.getLegacyPropertyToStringMode()); + Assert.assertEquals(true, configuration.isCloseIdleSessions()); + Assert.assertEquals(1234, configuration.getHeartbeatInterval()); + Assert.assertEquals(4321, configuration.getResourceCacheTime()); + + Class<? extends UI> uiClass = new DefaultUIProvider() + .getUIClass(new UIClassSelectionEvent(new VaadinServletRequest( + EasyMock.createMock(HttpServletRequest.class), servlet + .getService()))); + Assert.assertEquals(MockUI.class, uiClass); + } + + @Test + public void testValuesOverriddenForServlet() throws ServletException { + Properties servletInitParams = new Properties(); + servletInitParams.setProperty("productionMode", "false"); + servletInitParams.setProperty("heartbeatInterval", "1111"); + + TestServlet servlet = new TestServlet(); + servlet.init(new MockServletConfig(servletInitParams)); + DeploymentConfiguration configuration = servlet.getService() + .getDeploymentConfiguration(); + + // Values from servlet init params take precedence + Assert.assertEquals(1111, configuration.getHeartbeatInterval()); + Assert.assertEquals(false, configuration.isProductionMode()); + + // Other params are as defined in the annotation + Assert.assertEquals(LegacyProperyToStringMode.DISABLED, + configuration.getLegacyPropertyToStringMode()); + Assert.assertEquals(true, configuration.isCloseIdleSessions()); + Assert.assertEquals(4321, configuration.getResourceCacheTime()); + + Class<? extends UI> uiClass = new DefaultUIProvider() + .getUIClass(new UIClassSelectionEvent(new VaadinServletRequest( + EasyMock.createMock(HttpServletRequest.class), servlet + .getService()))); + Assert.assertEquals(MockUI.class, uiClass); + } +} + +@VaadinServletConfiguration(productionMode = true, ui = MockUI.class, closeIdleSessions = true, heartbeatInterval = 1234, resourceCacheTime = 4321) +class TestServlet extends VaadinServlet { + +} diff --git a/server/tests/src/com/vaadin/server/VaadinSessionTest.java b/server/tests/src/com/vaadin/server/VaadinSessionTest.java index 61a1581a6f..68f198410c 100644 --- a/server/tests/src/com/vaadin/server/VaadinSessionTest.java +++ b/server/tests/src/com/vaadin/server/VaadinSessionTest.java @@ -18,6 +18,7 @@ package com.vaadin.server; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.ReentrantLock; +import javax.servlet.ServletConfig; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionBindingEvent; @@ -30,7 +31,6 @@ import org.junit.Test; import com.vaadin.server.ClientConnector.DetachEvent; import com.vaadin.server.ClientConnector.DetachListener; -import com.vaadin.tests.util.MockDeploymentConfiguration; import com.vaadin.ui.UI; import com.vaadin.util.CurrentInstance; @@ -39,6 +39,7 @@ public class VaadinSessionTest { private VaadinSession session; private VaadinServlet mockServlet; private VaadinServletService mockService; + private ServletConfig mockServletConfig; private HttpSession mockHttpSession; private WrappedSession mockWrappedSession; private VaadinServletRequest vaadinRequest; @@ -46,24 +47,22 @@ public class VaadinSessionTest { @Before public void setup() throws Exception { - mockServlet = new VaadinServlet() { - @Override - public String getServletName() { - return "mockServlet"; - }; - }; - - mockService = new VaadinServletService(mockServlet, - new MockDeploymentConfiguration()); - mockService.init(); + mockServletConfig = new MockServletConfig(); + mockServlet = new VaadinServlet(); + mockServlet.init(mockServletConfig); + mockService = mockServlet.getService(); mockHttpSession = EasyMock.createMock(HttpSession.class); mockWrappedSession = new WrappedHttpSession(mockHttpSession) { final ReentrantLock lock = new ReentrantLock(); + { + lock.lock(); + } @Override public Object getAttribute(String name) { - if ("mockServlet.lock".equals(name)) { + String lockAttribute = mockService.getServiceName() + ".lock"; + if (lockAttribute.equals(name)) { return lock; } return super.getAttribute(name); diff --git a/server/tests/src/com/vaadin/tests/data/bean/AnotherTestEnum.java b/server/tests/src/com/vaadin/tests/data/bean/AnotherTestEnum.java new file mode 100644 index 0000000000..fc8f22a947 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/bean/AnotherTestEnum.java @@ -0,0 +1,16 @@ +package com.vaadin.tests.data.bean; + +public enum AnotherTestEnum { + ONE("ONE"), TWO("TWO"); + + private String id; + + private AnotherTestEnum(String id) { + this.id = id; + } + + @Override + public String toString() { + return id; + } +} diff --git a/server/tests/src/com/vaadin/tests/data/bean/TestEnum.java b/server/tests/src/com/vaadin/tests/data/bean/TestEnum.java new file mode 100644 index 0000000000..bf6f721052 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/bean/TestEnum.java @@ -0,0 +1,16 @@ +package com.vaadin.tests.data.bean; + +public enum TestEnum { + ONE("1"), TWO("2"); + + private String id; + + private TestEnum(String id) { + this.id = id; + } + + @Override + public String toString() { + return id; + } +} diff --git a/server/tests/src/com/vaadin/tests/data/converter/TestAnyEnumToStringConverter.java b/server/tests/src/com/vaadin/tests/data/converter/TestAnyEnumToStringConverter.java new file mode 100644 index 0000000000..c267e012e8 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/converter/TestAnyEnumToStringConverter.java @@ -0,0 +1,130 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.tests.data.converter; + +import java.util.Locale; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.converter.Converter; +import com.vaadin.data.util.converter.ReverseConverter; +import com.vaadin.tests.data.bean.AnotherTestEnum; +import com.vaadin.tests.data.bean.TestEnum; +import com.vaadin.ui.TextField; + +public class TestAnyEnumToStringConverter { + + public class AnyEnumToStringConverter implements Converter<Enum, String> { + + private Class<? extends Enum>[] enumClass; + + public AnyEnumToStringConverter(Class<? extends Enum>... enumClass) { + this.enumClass = enumClass; + } + + @Override + public String convertToModel(Enum value, Locale locale) + throws com.vaadin.data.util.converter.Converter.ConversionException { + if (value == null) { + return null; + } + + return value.toString(); + } + + @Override + public Enum convertToPresentation(String value, Locale locale) + throws com.vaadin.data.util.converter.Converter.ConversionException { + if (value == null) { + return null; + } + for (Class<? extends Enum> candidate : enumClass) { + for (Enum e : candidate.getEnumConstants()) { + if (e.toString().equals(value)) { + return e; + } + } + } + + return null; + } + + @Override + public Class<String> getModelType() { + return String.class; + } + + @Override + public Class<Enum> getPresentationType() { + return Enum.class; + } + + } + + private AnyEnumToStringConverter converter; + + @Before + public void setup() { + converter = new AnyEnumToStringConverter(TestEnum.class, + AnotherTestEnum.class); + } + + @Test + public void nullConversion() { + Assert.assertEquals(null, converter.convertToModel(null, null)); + } + + @Test + public void enumToStringConversion() { + Assert.assertEquals(TestEnum.TWO.toString(), + converter.convertToModel(TestEnum.TWO, null)); + Assert.assertEquals(AnotherTestEnum.TWO.toString(), + converter.convertToModel(AnotherTestEnum.TWO, null)); + } + + @Test + public void stringToEnumConversion() { + Assert.assertEquals(TestEnum.TWO, + converter.convertToPresentation(TestEnum.TWO.toString(), null)); + Assert.assertEquals(AnotherTestEnum.TWO, converter + .convertToPresentation(AnotherTestEnum.TWO.toString(), null)); + } + + @Test + public void stringToEnumWithField() { + TextField tf = new TextField(); + tf.setConverter(new ReverseConverter(converter)); + tf.setPropertyDataSource(new ObjectProperty(AnotherTestEnum.TWO)); + Assert.assertEquals(AnotherTestEnum.TWO.toString(), tf.getValue()); + tf.setValue(AnotherTestEnum.ONE.toString()); + Assert.assertEquals(AnotherTestEnum.ONE.toString(), tf.getValue()); + Assert.assertEquals(AnotherTestEnum.ONE, tf.getConvertedValue()); + Assert.assertEquals(AnotherTestEnum.ONE, tf.getPropertyDataSource() + .getValue()); + + tf.setPropertyDataSource(new ObjectProperty(TestEnum.TWO)); + Assert.assertEquals(TestEnum.TWO.toString(), tf.getValue()); + tf.setValue(TestEnum.ONE.toString()); + Assert.assertEquals(TestEnum.ONE.toString(), tf.getValue()); + Assert.assertEquals(TestEnum.ONE, tf.getConvertedValue()); + Assert.assertEquals(TestEnum.ONE, tf.getPropertyDataSource().getValue()); + + } +} diff --git a/server/tests/src/com/vaadin/tests/data/converter/TestSpecificEnumToStringConverter.java b/server/tests/src/com/vaadin/tests/data/converter/TestSpecificEnumToStringConverter.java new file mode 100644 index 0000000000..93dbe96b56 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/converter/TestSpecificEnumToStringConverter.java @@ -0,0 +1,121 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.tests.data.converter; + +import java.util.Locale; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.converter.Converter; +import com.vaadin.data.util.converter.ReverseConverter; +import com.vaadin.tests.data.bean.AnotherTestEnum; +import com.vaadin.tests.data.bean.TestEnum; +import com.vaadin.ui.TextField; + +public class TestSpecificEnumToStringConverter { + + public class SpecificEnumToStringConverter implements + Converter<Enum, String> { + + private Class<? extends Enum> enumClass; + + public SpecificEnumToStringConverter(Class<? extends Enum> enumClass) { + this.enumClass = enumClass; + } + + @Override + public String convertToModel(Enum value, Locale locale) + throws com.vaadin.data.util.converter.Converter.ConversionException { + if (value == null) { + return null; + } + + return value.toString(); + } + + @Override + public Enum convertToPresentation(String value, Locale locale) + throws com.vaadin.data.util.converter.Converter.ConversionException { + if (value == null) { + return null; + } + + for (Enum e : enumClass.getEnumConstants()) { + if (e.toString().equals(value)) { + return e; + } + } + + return null; + } + + @Override + public Class<String> getModelType() { + return String.class; + } + + @Override + public Class<Enum> getPresentationType() { + return (Class<Enum>) enumClass; + } + + } + + SpecificEnumToStringConverter testEnumConverter; + SpecificEnumToStringConverter anotherTestEnumConverter; + + @Before + public void setup() { + testEnumConverter = new SpecificEnumToStringConverter(TestEnum.class); + anotherTestEnumConverter = new SpecificEnumToStringConverter( + AnotherTestEnum.class); + } + + @Test + public void nullConversion() { + Assert.assertEquals(null, testEnumConverter.convertToModel(null, null)); + } + + @Test + public void enumToStringConversion() { + Assert.assertEquals(TestEnum.TWO.toString(), + testEnumConverter.convertToModel(TestEnum.TWO, null)); + } + + @Test + public void stringToEnumConversion() { + Assert.assertEquals(TestEnum.TWO, testEnumConverter + .convertToPresentation(TestEnum.TWO.toString(), null)); + } + + @Test + public void stringToEnumWithField() { + TextField tf = new TextField(); + tf.setConverter(new ReverseConverter(anotherTestEnumConverter)); + tf.setPropertyDataSource(new ObjectProperty(AnotherTestEnum.TWO)); + Assert.assertEquals(AnotherTestEnum.TWO.toString(), tf.getValue()); + tf.setValue(AnotherTestEnum.ONE.toString()); + Assert.assertEquals(AnotherTestEnum.ONE.toString(), tf.getValue()); + Assert.assertEquals(AnotherTestEnum.ONE, tf.getConvertedValue()); + Assert.assertEquals(AnotherTestEnum.ONE, tf.getPropertyDataSource() + .getValue()); + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java b/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java index 90cb6b9994..af6d9ed732 100644 --- a/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java +++ b/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java @@ -7,6 +7,7 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.Enumeration; import java.util.Iterator; import java.util.List; @@ -33,6 +34,7 @@ public class TestClassesSerializable extends TestCase { "com\\.vaadin\\.launcher\\..*", // "com\\.vaadin\\.client\\..*", // "com\\.vaadin\\.server\\.widgetsetutils\\..*", // + "com\\.vaadin\\.server\\.themeutils\\..*", // "com\\.vaadin\\.tests\\..*", // exclude automated tests "com\\.vaadin\\.tools\\..*", // "com\\.vaadin\\.ui\\.themes\\..*", // @@ -41,7 +43,13 @@ public class TestClassesSerializable extends TestCase { "com\\.vaadin\\.event\\.LayoutEvents", // "com\\.vaadin\\.event\\.MouseEvents", // "com\\.vaadin\\.server\\.VaadinPortlet", // + "com\\.vaadin\\.server\\.MockServletConfig", // + "com\\.vaadin\\.server\\.MockServletContext", // "com\\.vaadin\\.server\\.Constants", // + "com\\.vaadin\\.server\\.communication\\.FileUploadHandler\\$SimpleMultiPartInputStream", // + "com\\.vaadin\\.server\\.communication\\.PushRequestHandler.*", + "com\\.vaadin\\.server\\.communication\\.PushHandler.*", // PushHandler + // and its inner classes do not need to be serializable "com\\.vaadin\\.util\\.SerializerHelper", // fully static // class level filtering, also affecting nested classes and // interfaces @@ -50,6 +58,7 @@ public class TestClassesSerializable extends TestCase { "com\\.vaadin\\.util\\.ReflectTools.*", // "com\\.vaadin\\.data\\.util\\.ReflectTools.*", // "com\\.vaadin\\.sass.*", // + "com\\.vaadin\\.testbench.*", // "com\\.vaadin\\.util\\.CurrentInstance\\$1", // }; @@ -88,6 +97,19 @@ public class TestClassesSerializable extends TestCase { // report non-serializable classes and interfaces if (!Serializable.class.isAssignableFrom(cls)) { + if (cls.getSuperclass() == Object.class + && cls.getInterfaces().length == 1) { + // Single interface implementors + Class<?> iface = cls.getInterfaces()[0]; + + if (iface == Runnable.class) { + // Ignore Runnables used with access() + continue; + } else if (iface == Comparator.class) { + // Ignore inline comparators + continue; + } + } nonSerializableClasses.add(cls); // TODO easier to read when testing // System.err.println(cls); diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValidators.java b/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbsFieldValidators.java index 19c58fe6d3..764446f7aa 100644 --- a/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValidators.java +++ b/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbsFieldValidators.java @@ -8,7 +8,7 @@ import com.vaadin.data.Validator; import com.vaadin.ui.AbstractField; import com.vaadin.ui.Field; -public class AbstractFieldValidators extends TestCase { +public class AbsFieldValidators extends TestCase { Field<Object> field = new AbstractField<Object>() { @Override diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java b/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbsFieldValueConversions.java index 3c4d43543b..b5e937f27d 100644 --- a/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java +++ b/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbsFieldValueConversions.java @@ -21,7 +21,7 @@ import com.vaadin.tests.util.AlwaysLockedVaadinSession; import com.vaadin.ui.CheckBox; import com.vaadin.ui.TextField; -public class AbstractFieldValueConversions extends TestCase { +public class AbsFieldValueConversions extends TestCase { Person paulaBean = new Person("Paula", "Brilliant", "paula@brilliant.com", 34, Sex.FEMALE, new Address("Paula street 1", 12345, "P-town", diff --git a/server/tests/src/com/vaadin/ui/AbstractFieldDataSourceLocaleChange.java b/server/tests/src/com/vaadin/ui/AbsFieldDataSourceLocaleChange.java index 9810873f0b..acea0a84c7 100644 --- a/server/tests/src/com/vaadin/ui/AbstractFieldDataSourceLocaleChange.java +++ b/server/tests/src/com/vaadin/ui/AbsFieldDataSourceLocaleChange.java @@ -12,7 +12,7 @@ import com.vaadin.data.util.converter.StringToIntegerConverter; import com.vaadin.server.VaadinRequest; import com.vaadin.server.VaadinSession; -public class AbstractFieldDataSourceLocaleChange { +public class AbsFieldDataSourceLocaleChange { private VaadinSession vaadinSession; private UI ui; diff --git a/shared/build.xml b/shared/build.xml index 8520ee6eba..67dd3e9843 100644 --- a/shared/build.xml +++ b/shared/build.xml @@ -1,64 +1,66 @@ <?xml version="1.0"?> -<project name="vaadin-shared" basedir="." default="publish-local" xmlns:ivy="antlib:org.apache.ivy.ant"> - <description> - Compiles build helpers used when building other modules. - </description> - <include file="../common.xml" as="common" /> - <include file="../build.xml" as="vaadin" /> - <include file="../gwt-files.xml" as="gwtfiles" /> +<project name="vaadin-shared" basedir="." default="publish-local" + xmlns:ivy="antlib:org.apache.ivy.ant"> + <description> + Compiles build helpers used when building other modules. + </description> + <include file="../common.xml" as="common" /> + <include file="../build.xml" as="vaadin" /> + <include file="../gwt-files.xml" as="gwtfiles" /> - <!-- global properties --> - <property name="module.name" value="vaadin-shared" /> - <property name="module.symbolic" value="com.vaadin.shared" /> - <property name="result.dir" location="result" /> - <property name="src.filtered" location="${result.dir}/filtered-src" /> - <property name="src" location="${src.filtered}" /> - <path id="classpath.compile.custom" /> + <!-- global properties --> + <property name="module.name" value="vaadin-shared" /> + <property name="module.symbolic" value="com.vaadin.shared" /> + <property name="result.dir" location="result" /> + <property name="src.filtered" location="${result.dir}/filtered-src" /> + <property name="src" location="${src.filtered}" /> + <path id="classpath.compile.custom" /> - <target name="jar"> - <property name="shared.osgi.import" value="org.json;version="0.0.20080701", com.google.gwt.thirdparty.guava.common.annotations;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.base;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.base.internal;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.cache;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.collect;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.eventbus;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.io;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.net;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.primitives;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.util.concurrent;version="10.0.1.rebased", com.google.gwt.thirdparty.streamhtmlparser;version="0.1.5.r10-rebased", com.google.gwt.thirdparty.streamhtmlparser.impl;version="0.1.5.r10-rebased", com.google.gwt.thirdparty.streamhtmlparser.util;version="0.1.5.r10-rebased", org.w3c.flute.parser;version="1.3.0.gg2", org.w3c.flute.parser.selectors;version="1.3.0.gg2", org.w3c.flute.util;version="1.3.0.gg2"" /> - <delete dir="${src.filtered}" /> - <!-- Update version in Version.java --> - <copy todir="${src.filtered}"> - <fileset dir="src"> - </fileset> - <filterchain> - <replacetokens begintoken="@" endtoken="@"> - <token key="VERSION" value="${vaadin.version}" /> - </replacetokens> - </filterchain> - </copy> + <target name="jar"> + <property name="shared.osgi.import" + value="org.json;version="0.0.20080701", com.google.gwt.thirdparty.guava.common.annotations;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.base;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.base.internal;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.cache;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.collect;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.eventbus;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.io;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.net;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.primitives;version="10.0.1.rebased", com.google.gwt.thirdparty.guava.common.util.concurrent;version="10.0.1.rebased", com.google.gwt.thirdparty.streamhtmlparser;version="0.1.5.r10-rebased", com.google.gwt.thirdparty.streamhtmlparser.impl;version="0.1.5.r10-rebased", com.google.gwt.thirdparty.streamhtmlparser.util;version="0.1.5.r10-rebased", org.w3c.flute.parser;version="1.3.0.gg2", org.w3c.flute.parser.selectors;version="1.3.0.gg2", org.w3c.flute.util;version="1.3.0.gg2"" /> + <delete dir="${src.filtered}" /> + <!-- Update version in Version.java --> + <copy todir="${src.filtered}"> + <fileset dir="src"> + </fileset> + <filterchain> + <replacetokens begintoken="@" endtoken="@"> + <token key="VERSION" value="${vaadin.version}" /> + </replacetokens> + </filterchain> + </copy> - <antcall target="common.jar"> - <param name="import-package" value="${shared.osgi.import}" /> - <reference refid="shared.gwt.includes" torefid="extra.jar.includes" /> - </antcall> - </target> + <antcall target="common.jar"> + <param name="import-package" value="${shared.osgi.import}" /> + <reference refid="shared.gwt.includes" torefid="extra.jar.includes" /> + </antcall> + </target> - <target name="publish-local" depends="jar"> - <antcall target="common.sources.jar"> - <reference torefid="extra.jar.includes" refid="shared.gwt.includes" /> - </antcall> - <antcall target="common.javadoc.jar" /> + <target name="publish-local" depends="jar"> + <antcall target="common.sources.jar"> + <reference torefid="extra.jar.includes" refid="shared.gwt.includes" /> + </antcall> + <antcall target="common.javadoc.jar" /> - <antcall target="common.publish-local" /> - </target> + <antcall target="common.publish-local" /> + </target> - <target name="clean"> - <antcall target="common.clean" /> - </target> - - <target name="checkstyle"> - <antcall target="common.checkstyle"> - <param name="cs.src" location="src" /> - </antcall> - </target> + <target name="clean"> + <antcall target="common.clean" /> + </target> - <target name="test" depends="checkstyle"> - <!--<antcall target="common.test.run" />--> - <echo>WHAT? No tests for ${module.name}!</echo> - </target> + <target name="checkstyle"> + <antcall target="common.checkstyle"> + <param name="cs.src" location="src" /> + </antcall> + </target> + + <target name="test" depends="checkstyle"> + <!--<antcall target="common.test.run" /> --> + <echo>WHAT? No tests for ${module.name}!</echo> + </target> </project>
\ No newline at end of file diff --git a/shared/src/com/vaadin/shared/ApplicationConstants.java b/shared/src/com/vaadin/shared/ApplicationConstants.java index fc4abd1988..e51139dac7 100644 --- a/shared/src/com/vaadin/shared/ApplicationConstants.java +++ b/shared/src/com/vaadin/shared/ApplicationConstants.java @@ -39,9 +39,6 @@ public class ApplicationConstants implements Serializable { + "://"; public static final String UIDL_SECURITY_TOKEN_ID = "Vaadin-Security-Key"; - public static final String PARAM_ANALYZE_LAYOUTS = "analyzeLayouts"; - public static final String PARAM_HIGHLIGHT_CONNECTOR = "highlightConnector"; - @Deprecated public static final String UPDATE_VARIABLE_INTERFACE = "v"; @Deprecated @@ -83,8 +80,4 @@ public class ApplicationConstants implements Serializable { * Name of the parameter used to transmit the CSRF token. */ public static final String CSRF_TOKEN_PARAMETER = "v-csrfToken"; - - public static final int WEBSOCKET_BUFFER_SIZE = 65536; - - public static final char WEBSOCKET_MESSAGE_DELIMITER = '|'; } diff --git a/shared/src/com/vaadin/shared/communication/PushConstants.java b/shared/src/com/vaadin/shared/communication/PushConstants.java new file mode 100644 index 0000000000..f16cbb7390 --- /dev/null +++ b/shared/src/com/vaadin/shared/communication/PushConstants.java @@ -0,0 +1,46 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.shared.communication; + +import java.io.Serializable; + +/** + * Shared constants used by push. + * + * @since 7.1 + * @author Vaadin Ltd + */ +public class PushConstants implements Serializable { + + /** + * The size, in <b>bytes</b>, of the receiving buffer used by some servers. + */ + public static final int WEBSOCKET_BUFFER_SIZE = 65536; + + /** + * The maximum size, in <b>characters</b>, of a websocket message fragment. + * This is a conservative maximum chosen so that the size in bytes will not + * exceed {@link PushConstants#WEBSOCKET_BUFFER_SIZE} given a UTF-8 encoded + * message. + */ + public static final int WEBSOCKET_FRAGMENT_SIZE = WEBSOCKET_BUFFER_SIZE / 4 - 1; + + /** + * The character used to mark message boundaries when messages may be split + * into multiple fragments. + */ + public static final char MESSAGE_DELIMITER = '|'; +} diff --git a/shared/src/com/vaadin/shared/communication/SharedState.java b/shared/src/com/vaadin/shared/communication/SharedState.java index 17b6fd7ab4..57c3e801b5 100644 --- a/shared/src/com/vaadin/shared/communication/SharedState.java +++ b/shared/src/com/vaadin/shared/communication/SharedState.java @@ -54,9 +54,9 @@ public class SharedState implements Serializable { /** * The automatically managed resources used by the connector. * - * @see com.vaadin.terminal.AbstractClientConnector#setResource(String, - * com.vaadin.terminal.Resource) - * @see com.vaadin.terminal.gwt.client.ui.AbstractConnector#getResourceUrl(String) + * @see com.vaadin.server.AbstractClientConnector#setResource(String, + * com.vaadin.server.Resource) + * @see com.vaadin.client.ui.AbstractConnector#getResourceUrl(String) */ public Map<String, URLReference> resources = new HashMap<String, URLReference>(); diff --git a/shared/src/com/vaadin/shared/ui/calendar/CalendarEventId.java b/shared/src/com/vaadin/shared/ui/calendar/CalendarEventId.java index 6f52aabf43..27f1cdd341 100644 --- a/shared/src/com/vaadin/shared/ui/calendar/CalendarEventId.java +++ b/shared/src/com/vaadin/shared/ui/calendar/CalendarEventId.java @@ -15,6 +15,8 @@ */ package com.vaadin.shared.ui.calendar; +import java.io.Serializable; + /** * CalendarEventId contains static String identifiers for all Calendar events. * These are used both in the client and server side code. @@ -22,7 +24,7 @@ package com.vaadin.shared.ui.calendar; * @since 7.1 * @author Vaadin Ltd. */ -public class CalendarEventId { +public class CalendarEventId implements Serializable { public static final String EVENTMOVE = "eventMove"; public static final String RANGESELECT = "rangeSelect"; diff --git a/shared/src/com/vaadin/shared/ui/calendar/DateConstants.java b/shared/src/com/vaadin/shared/ui/calendar/DateConstants.java index 8a840274c2..9b1c995642 100644 --- a/shared/src/com/vaadin/shared/ui/calendar/DateConstants.java +++ b/shared/src/com/vaadin/shared/ui/calendar/DateConstants.java @@ -15,12 +15,14 @@ */ package com.vaadin.shared.ui.calendar; +import java.io.Serializable; + /** * * @since 7.1 * */ -public class DateConstants { +public class DateConstants implements Serializable { public static final String ACTION_DATE_FORMAT_PATTERN = "yyyy-MM-dd HH:mm:ss"; public static final String CLIENT_DATE_FORMAT = "yyyy-MM-dd"; diff --git a/shared/src/com/vaadin/shared/ui/progressindicator/ProgressBarState.java b/shared/src/com/vaadin/shared/ui/progressindicator/ProgressBarState.java new file mode 100644 index 0000000000..1cc8d7d9ae --- /dev/null +++ b/shared/src/com/vaadin/shared/ui/progressindicator/ProgressBarState.java @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.shared.ui.progressindicator; + +import com.vaadin.shared.AbstractFieldState; +import com.vaadin.shared.communication.SharedState; + +/** + * {@link SharedState} for {@link com.vaadin.ui.ProgressBar} + * + * @since 7.1 + * @author Vaadin Ltd + */ +public class ProgressBarState extends AbstractFieldState { + public static final String PRIMARY_STYLE_NAME = "v-progressbar"; + + { + primaryStyleName = PRIMARY_STYLE_NAME; + } + public boolean indeterminate = false; + public Float state = 0.0f; + +}
\ No newline at end of file diff --git a/shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorState.java b/shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorState.java index 4126b994d8..2ca7627f4f 100644 --- a/shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorState.java +++ b/shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorState.java @@ -15,10 +15,13 @@ */ package com.vaadin.shared.ui.progressindicator; -import com.vaadin.shared.AbstractFieldState; +@Deprecated +public class ProgressIndicatorState extends ProgressBarState { + public static final String PRIMARY_STYLE_NAME = "v-progressindicator"; + + { + primaryStyleName = PRIMARY_STYLE_NAME; + } -public class ProgressIndicatorState extends AbstractFieldState { - public boolean indeterminate = false; public int pollingInterval = 1000; - public Float state = 0.0f; } diff --git a/shared/src/com/vaadin/shared/ui/ui/DebugWindowClientRpc.java b/shared/src/com/vaadin/shared/ui/ui/DebugWindowClientRpc.java new file mode 100644 index 0000000000..7e76a6a459 --- /dev/null +++ b/shared/src/com/vaadin/shared/ui/ui/DebugWindowClientRpc.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.shared.ui.ui; + +import com.vaadin.shared.communication.ClientRpc; + +/** + * Client RPC methods for the Debug Window. + * + * @since 7.1 + * @author Vaadin Ltd + */ +public interface DebugWindowClientRpc extends ClientRpc { + + /** + * Send results from {@link DebugWindowServerRpc#analyzeLayouts()} back to + * the client. + * + * @since 7.1 + * @param json + * JSON containing list of found problems + */ + public void reportLayoutProblems(String json); + +} diff --git a/shared/src/com/vaadin/shared/ui/ui/DebugWindowServerRpc.java b/shared/src/com/vaadin/shared/ui/ui/DebugWindowServerRpc.java new file mode 100644 index 0000000000..76e7d23379 --- /dev/null +++ b/shared/src/com/vaadin/shared/ui/ui/DebugWindowServerRpc.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +/** + * + */ +package com.vaadin.shared.ui.ui; + +import com.vaadin.shared.Connector; +import com.vaadin.shared.communication.ServerRpc; + +/** + * Server RPC methods for the Debug Window. + * + * @since 7.1 + * @author Vaadin Ltd + */ +public interface DebugWindowServerRpc extends ServerRpc { + /** + * Sends a request to the server to print details to console that will help + * the developer to locate the corresponding server-side connector in the + * source code. + * + * @since 7.1 + * @param connector + * the connector to locate + **/ + public void showServerDebugInfo(Connector connector); + + /** + * Invokes the layout analyzer on the server + * + * @since 7.1 + */ + public void analyzeLayouts(); + +} diff --git a/shared/src/com/vaadin/shared/ui/ui/Transport.java b/shared/src/com/vaadin/shared/ui/ui/Transport.java new file mode 100644 index 0000000000..69d713bcca --- /dev/null +++ b/shared/src/com/vaadin/shared/ui/ui/Transport.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.shared.ui.ui; + +/** + * Transport modes for Push + * + * @since 7.1 + * @author Vaadin Ltd + */ +public enum Transport { + /** + * Websockets + */ + WEBSOCKET("websocket"), + /** + * HTTP streaming + */ + STREAMING("streaming"); + + /** + * The default transport mechanism for push + */ + public static final Transport DEFAULT = Transport.WEBSOCKET; + + /** + * The default fallback transport mechanism for push + */ + public static final Transport DEFAULT_FALLBACK = Transport.STREAMING; + + private String identifier; + + private Transport(String identifier) { + this.identifier = identifier; + } + + public String getIdentifier() { + return identifier; + } + +} diff --git a/shared/src/com/vaadin/shared/ui/ui/UIState.java b/shared/src/com/vaadin/shared/ui/ui/UIState.java index 16c1ed16c7..e19a87ada9 100644 --- a/shared/src/com/vaadin/shared/ui/ui/UIState.java +++ b/shared/src/com/vaadin/shared/ui/ui/UIState.java @@ -16,6 +16,10 @@ package com.vaadin.shared.ui.ui; import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import com.vaadin.shared.communication.PushMode; import com.vaadin.shared.ui.TabIndexState; @@ -25,8 +29,6 @@ public class UIState extends TabIndexState { public LoadingIndicatorConfigurationState loadingIndicatorConfiguration = new LoadingIndicatorConfigurationState(); public int pollInterval = -1; - public PushMode pushMode = PushMode.DISABLED; - // Informing users of assistive devices, that the content of this container // is announced automatically and does not need to be navigated into public String overlayContainerLabel = "This content is announced automatically and does not need to be navigated into."; @@ -46,14 +48,56 @@ public class UIState extends TabIndexState { public int maxWidth = 500; } + public static class PushConfigurationState implements Serializable { + public static final String TRANSPORT_PARAM = "transport"; + public static final String FALLBACK_TRANSPORT_PARAM = "fallbackTransport"; + + public PushMode mode = PushMode.DISABLED; + public Map<String, String> parameters = new HashMap<String, String>(); + { + parameters.put(TRANSPORT_PARAM, Transport.DEFAULT.getIdentifier()); + parameters.put(FALLBACK_TRANSPORT_PARAM, + Transport.DEFAULT_FALLBACK.getIdentifier()); + } + } + /** - * State related to the {@link Page} class. + * State related to the Page class. */ public PageState pageState = new PageState(); + /** + * State related to the LocaleService class. + */ + public LocaleServiceState localeServiceState = new LocaleServiceState(); + + /** + * Configuration for the push channel + */ + public PushConfigurationState pushConfiguration = new PushConfigurationState(); { primaryStyleName = "v-ui"; // Default is 1 for legacy reasons tabIndex = 1; } + + public static class LocaleServiceState implements Serializable { + public List<LocaleData> localeData = new ArrayList<LocaleData>(); + } + + public static class LocaleData implements Serializable { + public String name; + public String[] monthNames; + public String[] shortMonthNames; + public String[] shortDayNames; + public String[] dayNames; + public int firstDayOfWeek; + public String dateFormat; + public boolean twelveHourClock; + public String hourMinuteDelimiter; + public String am; + public String pm; + + } + } diff --git a/shared/src/com/vaadin/shared/ui/window/WindowServerRpc.java b/shared/src/com/vaadin/shared/ui/window/WindowServerRpc.java index cfb10ad86a..b43765274e 100644 --- a/shared/src/com/vaadin/shared/ui/window/WindowServerRpc.java +++ b/shared/src/com/vaadin/shared/ui/window/WindowServerRpc.java @@ -15,13 +15,11 @@ */ package com.vaadin.shared.ui.window; -import com.vaadin.shared.annotations.Delayed; import com.vaadin.shared.communication.ServerRpc; import com.vaadin.shared.ui.ClickRpc; public interface WindowServerRpc extends ClickRpc, ServerRpc { - @Delayed(lastOnly = true) public void windowModeChanged(WindowMode newState); }
\ No newline at end of file diff --git a/shared/src/com/vaadin/shared/util/SharedUtil.java b/shared/src/com/vaadin/shared/util/SharedUtil.java index 2242fa4363..80efe68d83 100644 --- a/shared/src/com/vaadin/shared/util/SharedUtil.java +++ b/shared/src/com/vaadin/shared/util/SharedUtil.java @@ -15,6 +15,8 @@ */ package com.vaadin.shared.util; +import java.io.Serializable; + /** * Misc internal utility methods used by both the server and the client package. * @@ -22,7 +24,7 @@ package com.vaadin.shared.util; * @since 7.1 * */ -public class SharedUtil { +public class SharedUtil implements Serializable { /** * Checks if a and b are equals using {@link #equals(Object)}. Handles null * values as well. Does not ensure that objects are of the same type. diff --git a/theme-compiler/build.xml b/theme-compiler/build.xml index 277929d160..b28eca8cf7 100644 --- a/theme-compiler/build.xml +++ b/theme-compiler/build.xml @@ -1,58 +1,64 @@ <?xml version="1.0"?> -<project name="vaadin-theme-compiler" basedir="." default="publish-local" xmlns:ivy="antlib:org.apache.ivy.ant"> - <description> - Compiles build helpers used when building other modules. - </description> - <include file="../common.xml" as="common" /> - <include file="../build.xml" as="vaadin" /> - <include file="../gwt-files.xml" as="gwtfiles" /> - - <!-- global properties --> - <property name="module.name" value="vaadin-theme-compiler" /> - <property name="module.symbolic" value="com.vaadin.theme-compiler" /> - <property name="result.dir" value="result" /> - <property name="sass.parser.jj" location="src/com/vaadin/sass/internal/parser/Parser.jj" /> - <path id="classpath.compile.custom"> - </path> - <path id="classpath.test.custom" /> - - <!--<property name="classes.exclude" value="com/vaadin/buildhelpers/**" />--> - - <target name="parser"> - <!-- Copy javacc-5.0.jar to ${result.dir}/javacc/javacc.jar as the javacc task requires the jar to be named javacc.jar --> - <property name="javacc.home" location="${result.dir}/javacc" /> - <ivy:retrieve organisation="net.java.dev.javacc" module="javacc" revision="5.0" inline="true" type="jar" pattern="${javacc.home}/[artifact].[ext]" /> - <javacc target="${sass.parser.jj}" javacchome="${javacc.home}"> - </javacc> - </target> - - <target name="jar" depends="parser"> - <antcall target="common.jar"> - <reference torefid="extra.jar.includes" refid="empty.reference" /> - </antcall> - </target> - <target name="publish-local" depends="jar"> - <antcall target="common.sources.jar"> - <reference torefid="extra.jar.includes" refid="empty.reference" /> - </antcall> - <antcall target="common.javadoc.jar" /> - - <antcall target="common.publish-local" /> - </target> - - <target name="clean"> - <antcall target="common.clean" /> - </target> - - <target name="checkstyle"> - <antcall target="common.checkstyle"> - <param name="cs.src" location="src" /> - </antcall> - </target> - - <target name="test" depends="checkstyle"> - <antcall target="common.test.run" /> - </target> +<project name="vaadin-theme-compiler" basedir="." default="publish-local" + xmlns:ivy="antlib:org.apache.ivy.ant"> + <description> + Compiles build helpers used when building other modules. + </description> + <include file="../common.xml" as="common" /> + <include file="../build.xml" as="vaadin" /> + <include file="../gwt-files.xml" as="gwtfiles" /> + + <!-- global properties --> + <property name="module.name" value="vaadin-theme-compiler" /> + <property name="module.symbolic" value="com.vaadin.theme-compiler" /> + <property name="result.dir" value="result" /> + <property name="sass.parser.jj" + location="src/com/vaadin/sass/internal/parser/Parser.jj" /> + <path id="classpath.compile.custom"> + </path> + <path id="classpath.test.custom" /> + + <!--<property name="classes.exclude" value="com/vaadin/buildhelpers/**" + /> --> + + <target name="parser"> + <!-- Copy javacc-5.0.jar to ${result.dir}/javacc/javacc.jar as the + javacc task requires the jar to be named javacc.jar --> + <property name="javacc.home" location="${result.dir}/javacc" /> + <ivy:retrieve organisation="net.java.dev.javacc" + module="javacc" revision="5.0" inline="true" type="jar" + pattern="${javacc.home}/[artifact].[ext]" /> + <javacc target="${sass.parser.jj}" javacchome="${javacc.home}"> + </javacc> + </target> + + <target name="jar" depends="parser"> + <antcall target="common.jar"> + <reference torefid="extra.jar.includes" refid="empty.reference" /> + </antcall> + </target> + <target name="publish-local" depends="jar"> + <antcall target="common.sources.jar"> + <reference torefid="extra.jar.includes" refid="empty.reference" /> + </antcall> + <antcall target="common.javadoc.jar" /> + + <antcall target="common.publish-local" /> + </target> + + <target name="clean"> + <antcall target="common.clean" /> + </target> + + <target name="checkstyle"> + <antcall target="common.checkstyle"> + <param name="cs.src" location="src" /> + </antcall> + </target> + + <target name="test" depends="checkstyle"> + <antcall target="common.test.run" /> + </target> </project>
\ No newline at end of file diff --git a/theme-compiler/ivy.xml b/theme-compiler/ivy.xml index f0646c04e6..97ecfa4416 100644 --- a/theme-compiler/ivy.xml +++ b/theme-compiler/ivy.xml @@ -45,11 +45,9 @@ <!-- Internally used, for now --> <dependency org="com.carrotsearch" name="smartsprites" - rev="0.2.3-itmill" /> - <!-- Use 1.1.1 even though smartsprites indirectly depends on an - older version --> - <override org="commons-logging" module="commons-logging" - rev="1.1.1"/> + rev="0.2.10-vaadin" /> + <!-- Use the same commons-io as the rest of the project --> + <override org="commons-io" module="commons-io" rev="2.2" /> </dependencies> </ivy-module> diff --git a/theme-compiler/ivymodule/smartsprites-ivy-0.2.3-itmill.xml b/theme-compiler/ivymodule/smartsprites-ivy-0.2.3-itmill.xml deleted file mode 100644 index 29dc2d3474..0000000000 --- a/theme-compiler/ivymodule/smartsprites-ivy-0.2.3-itmill.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ivy-module version="2.0" xmlns:m="http://ant.apache.org/ivy/maven"> - <info organisation="com.carrotsearch" - module="smartsprites" - revision="0.2.3-itmill" - status="release" - publication="20111130000000"> - <license name="BSD license" url="http://csssprites.org/smartsprites.LICENSE" /> - <description homepage="http://csssprites.org"> - CSS Sprites Generator Done Right. SmartSprites maintains CSS sprites in your designs, - fully automatically. No tedious copying and pasting to your CSS when adding or changing - sprited images. - </description> - </info> - <configurations> - <conf name="default" visibility="public" description="runtime dependencies and master artifact can be used with this conf" extends="runtime,master"/> - <conf name="master" visibility="public" description="contains only the artifact published by this module itself, with no transitive dependencies"/> - <conf name="compile" visibility="public" description="this is the default scope, used if none is specified. Compile dependencies are available in all classpaths."/> - <conf name="provided" visibility="public" description="this is much like compile, but indicates you expect the JDK or a container to provide it. It is only available on the compilation classpath, and is not transitive."/> - <conf name="runtime" visibility="public" description="this scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath." extends="compile"/> - <conf name="test" visibility="private" description="this scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases." extends="runtime"/> - <conf name="system" visibility="public" description="this scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository."/> - <conf name="sources" visibility="public" description="this configuration contains the source artifact of this module, if any."/> - <conf name="javadoc" visibility="public" description="this configuration contains the javadoc artifact of this module, if any."/> - <conf name="optional" visibility="public" description="contains all optional dependencies"/> - </configurations> - <publications> - <artifact name="smartsprites" type="jar" ext="jar" conf="master"/> - </publications> - <dependencies> - <dependency org="com.google.collections" name="google-collections" rev="0.9" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/> - <dependency org="args4j" name="args4j" rev="2.0.9" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/> - <dependency org="commons-math" name="commons-math" rev="1.1" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/> - <dependency org="commons-io" name="commons-io" rev="2.2" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/> - <dependency org="commons-lang" name="commons-lang" rev="2.6" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/> - <dependency org="junit" name="junit" rev="4.4" force="true" conf="test->runtime(*),master(*)"/> - </dependencies> -</ivy-module> diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java b/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java index d938dfefe8..382e8e6711 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java @@ -136,6 +136,7 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { * @exception IOException the source can't be parsed. * @exception CSSException the source is not CSS valid. */ + // TODO required by original parser but not used by Vaadin? public void parseRule(InputSource source) throws CSSException, IOException { this.source = source; @@ -1870,6 +1871,7 @@ char connector = ' '; case IDENT: case VARIABLE: case HASH: + case IMPORT_SYM: case MEDIA_SYM: case KEY_FRAME_SYM: ; @@ -1907,6 +1909,9 @@ char connector = ' '; case MICROSOFT_RULE: microsoftExtension(); break; + case IMPORT_SYM: + importDeclaration(); + break; default: jj_la1[69] = jj_gen; jj_consume_token(-1); @@ -6080,6 +6085,7 @@ LexicalUnitImpl result = null; * The following functions are useful for a DOM CSS implementation only and are * not part of the general CSS2 parser. */ +// TODO required by original parser but not used by Vaadin? final public void _parseRule() throws ParseException { String ret = null; label_168: @@ -7364,13 +7370,13 @@ LexicalUnitImpl result = null; return false; } - private boolean jj_3R_261() { - if (jj_scan_token(INTERPOLATION)) return true; + private boolean jj_3_9() { + if (jj_3R_184()) return true; return false; } - private boolean jj_3_9() { - if (jj_3R_184()) return true; + private boolean jj_3R_261() { + if (jj_scan_token(INTERPOLATION)) return true; return false; } @@ -7529,7 +7535,7 @@ LexicalUnitImpl result = null; jj_la1_2 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x401,0x4000,0x0,0x0,0x0,0x0,0x2200,0x0,0x0,0x0,0x400,0x400,0x0,0x0,0x8000,0x0,0x8000,0x0,0x0,0x4465,0x4465,0x0,0x0,0x0,0xae00,0xae00,0x0,0x0,0x0,0x400,0x0,0x0,0x400,0x0,0x0,0x400,0x0,0x0,0x0,0x0,0x400,0x0,0x0,0x400,0x0,0xaa00,0x0,0x0,0x0,0x0,0x0,0xe00,0xe00,0x0,0x400,0x400,0x0,0x0,0x0,0x0,0x4465,0x4465,0x0,0x0,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x400,0x400,0x400,0x400,0x400,0x400,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x0,0x0,0x400,0x0,0x100,0x0,0x0,0x1,0x424,0x4000,0x4c00,0x0,0x4424,0x0,0x2,0x0,0x4c00,0x80,0x0,0x4424,0x0,0x4c00,0x0,0x0,0x0,0x4400,0x0,0x4424,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x400,0x0,0x4425,0x4425,0x0,0x0,0x0,0x0,0x0,0x0,0x4000,0x4000,0xffffee00,0x0,0x0,0x0,0x0,0xffffee00,0x0,0x0,0x0,0x4400,0x0,0x0,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x400,0x0,0x0,0x400,0x0,0x0,0x400,0x0,0x0,0x0,0x400,0x0,0x0,0x400,0x0,0xffffee00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffffee00,0x0,0xffff8800,0x0,0x400,0x2600,0xffffae00,0x0,0x0,0xffffee00,0x0,0x400,0x0,0x0,0x0,0x400,0x0,0x0,0x400,0x0,}; } private static void jj_la1_init_3() { - jj_la1_3 = new int[] {0x20,0x200,0x200,0x8,0x200,0x0,0x0,0x0,0x1d4,0x0,0x200,0x0,0x200,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x114,0x114,0x0,0x0,0x0,0x31006fc,0x31006fc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x31006f8,0x0,0x0,0x0,0x0,0x0,0x1000000,0x1000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x114,0x114,0x0,0x0,0x0,0x4,0x0,0x4,0x4,0x0,0x0,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000000,0x0,0x0,0x0,0x0,0x0,0x114,0x0,0x800000,0x0,0x114,0x0,0x0,0x0,0x800000,0x0,0x0,0x114,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x114,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000000,0x0,0x1d4,0x1d4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1100007,0x0,0x0,0x0,0x0,0x1100007,0x0,0x0,0x0,0x1000000,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0xe00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x1100007,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1100007,0x0,0x1000003,0x0,0x0,0x100004,0x1100007,0x0,0x0,0x1100007,0x0,0xdc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,}; + jj_la1_3 = new int[] {0x20,0x200,0x200,0x8,0x200,0x0,0x0,0x0,0x1d4,0x0,0x200,0x0,0x200,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x114,0x114,0x0,0x0,0x0,0x31006fc,0x31006fc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x31006f8,0x0,0x0,0x0,0x0,0x0,0x1000000,0x1000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x11c,0x11c,0x0,0x0,0x0,0x4,0x0,0x4,0x4,0x0,0x0,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000000,0x0,0x0,0x0,0x0,0x0,0x114,0x0,0x800000,0x0,0x114,0x0,0x0,0x0,0x800000,0x0,0x0,0x114,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x114,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000000,0x0,0x1d4,0x1d4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1100007,0x0,0x0,0x0,0x0,0x1100007,0x0,0x0,0x0,0x1000000,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0xe00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x1100007,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1100007,0x0,0x1000003,0x0,0x0,0x100004,0x1100007,0x0,0x0,0x1100007,0x0,0xdc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,}; } final private JJCalls[] jj_2_rtns = new JJCalls[9]; private boolean jj_rescan = false; diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.jj b/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.jj index 7f86527015..daf20423d6 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.jj +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.jj @@ -169,6 +169,7 @@ public class Parser implements org.w3c.css.sac.Parser { * @exception IOException the source can't be parsed. * @exception CSSException the source is not CSS valid. */ + // TODO required by original parser but not used by Vaadin? public void parseRule(InputSource source) throws CSSException, IOException { this.source = source; @@ -1188,7 +1189,8 @@ void styleRule() : start = true; documentHandler.startSelector(l); } - ( ifContentStatement() | controlDirective() | microsoftExtension() )* + // a CSS import here will not work + ( ifContentStatement() | controlDirective() | microsoftExtension() | importDeclaration() )* <RBRACE> (<S>)* } catch (ThrowedParseException e) { if (errorHandler != null) { @@ -2947,7 +2949,7 @@ String skipAfterExpression() { * The following functions are useful for a DOM CSS implementation only and are * not part of the general CSS2 parser. */ - +// TODO required by original parser but not used by Vaadin? void _parseRule() : {String ret = null; } diff --git a/theme-compiler/src/com/vaadin/sass/internal/tree/ImportNode.java b/theme-compiler/src/com/vaadin/sass/internal/tree/ImportNode.java index f7d664d54d..6dc95db5c2 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/tree/ImportNode.java +++ b/theme-compiler/src/com/vaadin/sass/internal/tree/ImportNode.java @@ -18,7 +18,6 @@ package com.vaadin.sass.internal.tree; import org.w3c.css.sac.SACMediaList; -import com.vaadin.sass.internal.ScssStylesheet; import com.vaadin.sass.internal.visitor.ImportNodeHandler; public class ImportNode extends Node { @@ -74,7 +73,7 @@ public class ImportNode extends Node { @Override public void traverse() { - // TODO shouldn't be reached with current setup, try anyway? - ImportNodeHandler.traverse((ScssStylesheet) getParentNode()); + // nested imports + ImportNodeHandler.traverse(getParentNode()); } } diff --git a/theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java b/theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java index e356ed3525..cb9896967a 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java +++ b/theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java @@ -26,6 +26,7 @@ import org.w3c.css.sac.LexicalUnit; import com.vaadin.sass.internal.ScssStylesheet; import com.vaadin.sass.internal.parser.LexicalUnitImpl; +import com.vaadin.sass.internal.parser.ParseException; import com.vaadin.sass.internal.tree.ImportNode; import com.vaadin.sass.internal.tree.Node; import com.vaadin.sass.internal.tree.RuleNode; @@ -33,7 +34,23 @@ import com.vaadin.sass.internal.util.StringUtil; public class ImportNodeHandler { - public static void traverse(ScssStylesheet node) { + public static void traverse(Node node) { + ScssStylesheet styleSheet = null; + if (node instanceof ScssStylesheet) { + styleSheet = (ScssStylesheet) node; + } else { + // iterate to parents of node, find ScssStylesheet + Node parent = node.getParentNode(); + while (parent != null && !(parent instanceof ScssStylesheet)) { + parent = parent.getParentNode(); + } + if (parent instanceof ScssStylesheet) { + styleSheet = (ScssStylesheet) parent; + } + } + if (styleSheet == null) { + throw new ParseException("Nested import in an invalid context"); + } ArrayList<Node> c = new ArrayList<Node>(node.getChildren()); for (Node n : c) { if (n instanceof ImportNode) { @@ -41,7 +58,7 @@ public class ImportNodeHandler { if (!importNode.isPureCssImport()) { try { StringBuilder filePathBuilder = new StringBuilder( - node.getFileName()); + styleSheet.getFileName()); filePathBuilder.append(File.separatorChar).append( importNode.getUri()); if (!filePathBuilder.toString().endsWith(".scss")) { @@ -50,7 +67,8 @@ public class ImportNodeHandler { // set parent's charset to imported node. ScssStylesheet imported = ScssStylesheet.get( - filePathBuilder.toString(), node.getCharset()); + filePathBuilder.toString(), + styleSheet.getCharset()); if (imported == null) { imported = ScssStylesheet.get(importNode.getUri()); } @@ -76,6 +94,11 @@ public class ImportNodeHandler { } catch (IOException e) { e.printStackTrace(); } + } else { + if (styleSheet != node) { + throw new ParseException( + "CSS imports can only be used at the top level, not as nested imports. Within style rules, use SCSS imports."); + } } } } diff --git a/theme-compiler/tests/resources/automatic/css/nested-import.css b/theme-compiler/tests/resources/automatic/css/nested-import.css new file mode 100644 index 0000000000..7c6793f9ed --- /dev/null +++ b/theme-compiler/tests/resources/automatic/css/nested-import.css @@ -0,0 +1,5 @@ +.foo .bar { + background: url(foo/lorem.png); + background: url(foo/lorem.png); + background: url(foo/lorem.png); +}
\ No newline at end of file diff --git a/theme-compiler/tests/resources/automatic/scss/nested-import.scss b/theme-compiler/tests/resources/automatic/scss/nested-import.scss new file mode 100644 index 0000000000..605d64a13a --- /dev/null +++ b/theme-compiler/tests/resources/automatic/scss/nested-import.scss @@ -0,0 +1,3 @@ +.foo { + @import "foo/bar.scss"; +}
\ No newline at end of file diff --git a/themes/build.xml b/themes/build.xml index 75b3e5a903..5bca50e5f5 100644 --- a/themes/build.xml +++ b/themes/build.xml @@ -1,107 +1,115 @@ <?xml version="1.0"?> -<project name="vaadin-themes" basedir="." default="publish-local" xmlns:ivy="antlib:org.apache.ivy.ant"> - <description> - Themes compiled to CSS - </description> - - <include file="../common.xml" as="common" /> - <include file="../build.xml" as="vaadin" /> - <include file="../gwt-files.xml" as="gwtfiles" /> - - <!-- global properties --> - <property name="module.name" value="vaadin-themes" /> - <property name="module.symbolic" value="com.vaadin.themes" /> - <property name="result.dir" value="result" /> - <property name="theme.result.dir" value="${result.dir}/VAADIN/themes/" /> - - <union id="jar.includes"> - <fileset dir="${result.dir}"> - <include name="VAADIN/themes/**" /> - </fileset> - </union> - - <target name="compile-themes"> - <ivy:resolve resolveid="common" conf="build" /> - <ivy:cachepath pathid="classpath.compile.theme" conf="build" /> - - <antcall target="compile-theme"> - <param name="theme" value="base" /> - </antcall> - <antcall target="compile-theme"> - <param name="theme" value="runo" /> - </antcall> - <antcall target="compile-theme"> - <param name="theme" value="reindeer" /> - </antcall> - <antcall target="compile-theme"> - <param name="theme" value="chameleon" /> - </antcall> - <antcall target="compile-theme"> - <param name="theme" value="liferay" /> - </antcall> - </target> - - <target name="jar" depends="compile-themes"> - <antcall target="common.jar"> - <param name="osgi.extra.package.prefixes" value="VAADIN/themes" /> - <reference torefid="extra.jar.includes" refid="jar.includes" /> - </antcall> - </target> - - <target name="copy-theme"> - <fail unless="theme" message="You must give the theme name to copy n the 'theme' parameter" /> - <property name="theme.source.dir" location="../WebContent/VAADIN/themes" /> - - <copy todir="${theme.result.dir}"> - <fileset dir="${theme.source.dir}"> - <include name="${theme}/**" /> - </fileset> - </copy> - </target> - - <target name="compile-theme" depends="copy-theme"> - <fail unless="theme" message="You must give the theme name to compile in the 'theme' parameter" /> - - <ivy:resolve resolveid="common" conf="compile-theme" /> - <ivy:cachepath pathid="classpath.compile.theme" conf="compile-theme" /> - <ivy:cachepath pathid="classpath.runtime.theme" conf="build" /> - - <echo>Compiling ${theme}</echo> - <mkdir dir="${theme.result.dir}" /> - - <!-- compile the theme --> - <java classname="com.vaadin.buildhelpers.CompileTheme" classpathref="classpath.compile.theme" failonerror="yes" fork="yes" maxmemory="512m"> - <arg value="--theme" /> - <arg value="${theme}" /> - <arg value="--theme-folder" /> - <arg value="${theme.result.dir}" /> - <arg value="--theme-version" /> - <arg value="${vaadin.version}" /> - <jvmarg value="-Xss8M" /> - <jvmarg value="-XX:MaxPermSize=256M" /> - <jvmarg value="-Djava.awt.headless=true" /> - </java> - - </target> - - - <target name="publish-local" depends="jar"> - <antcall target="common.publish-local"> - - </antcall> - </target> - - <target name="clean"> - <antcall target="common.clean" /> - </target> - - <target name="checkstyle"> - <echo>No java files in module</echo> - </target> - <target name="test" depends="checkstyle"> - <!--<antcall target="common.test.run" />--> - <echo>WHAT? No tests for ${module.name}!</echo> - </target> +<project name="vaadin-themes" basedir="." default="publish-local" + xmlns:ivy="antlib:org.apache.ivy.ant"> + <description> + Themes compiled to CSS + </description> + + <include file="../common.xml" as="common" /> + <include file="../build.xml" as="vaadin" /> + <include file="../gwt-files.xml" as="gwtfiles" /> + + <!-- global properties --> + <property name="module.name" value="vaadin-themes" /> + <property name="module.symbolic" value="com.vaadin.themes" /> + <property name="result.dir" value="result" /> + <property name="theme.result.dir" value="${result.dir}/VAADIN/themes/" /> + + <union id="jar.includes"> + <fileset dir="${result.dir}"> + <include name="VAADIN/themes/**" /> + </fileset> + </union> + + <target name="compile-themes"> + <ivy:resolve resolveid="common" conf="build" /> + <ivy:cachepath pathid="classpath.compile.theme" + conf="build" /> + + <antcall target="compile-theme"> + <param name="theme" value="base" /> + </antcall> + <antcall target="compile-theme"> + <param name="theme" value="runo" /> + </antcall> + <antcall target="compile-theme"> + <param name="theme" value="reindeer" /> + </antcall> + <antcall target="compile-theme"> + <param name="theme" value="chameleon" /> + </antcall> + <antcall target="compile-theme"> + <param name="theme" value="liferay" /> + </antcall> + </target> + + <target name="jar" depends="compile-themes"> + <antcall target="common.jar"> + <param name="osgi.extra.package.prefixes" value="VAADIN/themes" /> + <reference torefid="extra.jar.includes" refid="jar.includes" /> + </antcall> + </target> + + <target name="copy-theme"> + <fail unless="theme" + message="You must give the theme name to copy n the 'theme' parameter" /> + <property name="theme.source.dir" location="../WebContent/VAADIN/themes" /> + + <copy todir="${theme.result.dir}"> + <fileset dir="${theme.source.dir}"> + <include name="${theme}/**" /> + </fileset> + </copy> + </target> + + <target name="compile-theme" depends="copy-theme"> + <fail unless="theme" + message="You must give the theme name to compile in the 'theme' parameter" /> + + <ivy:resolve resolveid="common" conf="compile-theme" /> + <ivy:cachepath pathid="classpath.compile.theme" + conf="compile-theme" /> + <ivy:cachepath pathid="classpath.runtime.theme" + conf="build" /> + + <echo>Compiling ${theme}</echo> + <mkdir dir="${theme.result.dir}" /> + + <!-- compile the theme --> + <java classname="com.vaadin.buildhelpers.CompileTheme" + classpathref="classpath.compile.theme" failonerror="yes" + fork="yes" maxmemory="512m"> + <arg value="--theme" /> + <arg value="${theme}" /> + <arg value="--theme-folder" /> + <arg value="${theme.result.dir}" /> + <arg value="--theme-version" /> + <arg value="${vaadin.version}" /> + <jvmarg value="-Xss8M" /> + <jvmarg value="-XX:MaxPermSize=256M" /> + <jvmarg value="-Djava.awt.headless=true" /> + </java> + + </target> + + + <target name="publish-local" depends="jar"> + <antcall target="common.publish-local"> + + </antcall> + </target> + + <target name="clean"> + <antcall target="common.clean" /> + </target> + + <target name="checkstyle"> + <echo>No java files in module</echo> + </target> + <target name="test" depends="checkstyle"> + <!--<antcall target="common.test.run" /> --> + <echo>WHAT? No tests for ${module.name}!</echo> + </target> </project> diff --git a/themes/ivy.xml b/themes/ivy.xml index e0e22429ab..beb1b16a00 100644 --- a/themes/ivy.xml +++ b/themes/ivy.xml @@ -14,8 +14,8 @@ </configurations> <publications> <artifact type="jar" ext="jar" /> -<!-- <artifact type="source" ext="jar" m:classifier="sources" /> --> -<!-- <artifact type="javadoc" ext="jar" m:classifier="javadoc" /> --> + <!-- <artifact type="source" ext="jar" m:classifier="sources" /> --> + <!-- <artifact type="javadoc" ext="jar" m:classifier="javadoc" /> --> <artifact type="pom" ext="pom" /> </publications> <dependencies> diff --git a/uitest/build.xml b/uitest/build.xml index 453fc26ea5..dc9258a807 100644 --- a/uitest/build.xml +++ b/uitest/build.xml @@ -1,148 +1,161 @@ <?xml version="1.0"?> -<project name="vaadin-uitest" basedir="." default="publish-local" xmlns:ivy="antlib:org.apache.ivy.ant"> - <description> - Provides a uitest WAR containing Vaadin UI tests - </description> - <include file="../common.xml" as="common" /> - <include file="../build.xml" as="vaadin" /> - - <!-- global properties --> - <property name="module.name" value="vaadin-uitest" /> - <property name="result.dir" value="result" /> - <property name="result.war" location="${result.dir}/lib/${module.name}-${vaadin.version}.war" /> - - <path id="classpath.compile.custom"> - </path> - - <target name="dependencies"> - <!-- This is copied from common.xml to be able to add server.test.source to the source path --> - - <ivy:resolve resolveid="common" conf="build, build-provided" /> - <ivy:cachepath pathid="classpath.compile.dependencies" conf="build, build-provided" /> - </target> - - <target name="compile" description="Compiles the module" depends="dependencies"> - - <fail unless="module.name" message="No module name given" /> - <property name="result.dir" location="result" /> - <property name="src" location="${result.dir}/../src" /> - <property name="classes" location="${result.dir}/classes" /> - <property name="server.test.sources" location="${result.dir}/../../server/tests/src" /> - <mkdir dir="${classes}" /> - - <!-- TODO: Get rid of this --> - <javac destdir="${classes}" source="${vaadin.java.version}" target="${vaadin.java.version}" debug="true" encoding="UTF-8" includeantruntime="false"> - <src path="${server.test.sources}" /> - <include name="com/vaadin/tests/data/bean/**" /> - <include name="com/vaadin/tests/VaadinClasses.java" /> - <include name="com/vaadin/data/util/sqlcontainer/SQLTestsConstants.java" /> - <classpath refid="classpath.compile.dependencies" /> - <classpath refid="classpath.compile.custom" /> - </javac> - - <javac destdir="${classes}" source="${vaadin.java.version}" target="${vaadin.java.version}" debug="true" encoding="UTF-8" includeantruntime="false"> - <src path="${src}" /> - <classpath location="${classes}" /> - <classpath refid="classpath.compile.dependencies" /> - <classpath refid="classpath.compile.custom" /> - </javac> - </target> - - <target name="testing-widgetset" depends="dependencies,compile"> - <property name="module" value="com.vaadin.tests.widgetset.TestingWidgetSet" /> - <property name="style" value="OBF" /> - <property name="localWorkers" value="2" /> - <property name="extraParams" value="" /> - <property name="module.output.dir" location="${result.dir}/VAADIN/widgetsets" /> - <property name="work.dir" location="${result.dir}/work" /> - - <mkdir dir="${module.output.dir}" /> - - <echo>Compiling ${module} to ${module.output.dir}</echo> - - <!-- compile the module --> - <java classname="com.google.gwt.dev.Compiler" classpathref="classpath.compile.dependencies" failonerror="yes" fork="yes" maxmemory="512m"> - <classpath location="src" /> - <classpath location="${classes}" /> - <arg value="-workDir" /> - <arg value="${work.dir}" /> - <arg value="-logLevel" /> - <arg value="TRACE" /> - <arg value="-war" /> - <arg value="${module.output.dir}" /> - <arg value="-style" /> - <arg value="${style}" /> - - <arg value="-localWorkers" /> - <arg value="${localWorkers}" /> - <arg value="-strict" /> - <arg line="${extraParams}" /> - <arg value="${module}" /> - - <sysproperty key="vFailIfNotSerializable" value="true" /> - - <jvmarg value="-Xss8M" /> - <jvmarg value="-XX:MaxPermSize=256M" /> - <jvmarg value="-Djava.awt.headless=true" /> - </java> - - </target> - - <target name="war" depends="dependencies, compile, testing-widgetset"> - <property name="result.dir" location="result" /> - <property name="classes" location="${result.dir}/classes" /> - <property name="WebContent.dir" location="${vaadin.basedir}/WebContent" /> - <property name="deps.dir" location="${result.dir}/deps" /> - <property name="src" location="${result.dir}/../src" /> - - <ivy:resolve resolveid="common" conf="build" /> - <ivy:cachepath pathid="classpath.runtime.dependencies" conf="build" /> - - <delete dir="${deps.dir}" /> - <mkdir dir="${deps.dir}" /> - - <copy todir="${deps.dir}" flatten="true"> - <path refid="classpath.runtime.dependencies" /> - </copy> - - - <!-- Ensure filtered webcontent files are available --> - <antcall target="common.filter.webcontent" /> - - <war destfile="${result.war}" duplicate="fail" index="true"> - <fileset refid="common.files.for.all.jars" /> - <fileset dir="${result.dir}"> - <include name="VAADIN/widgetsets/**/*"/> - </fileset> - <fileset dir="${WebContent.dir}"> - <include name="statictestfiles/**" /> - <include name="VAADIN/themes/tests-*/**" /> - <include name="VAADIN/themes/reindeer-tests/**" /> - <include name="WEB-INF/*.xml" /> - </fileset> - <classes dir="${classes}" /> - <classes dir="${src}" /> - <lib dir="${deps.dir}" /> - </war> - - </target> - - <target name="publish-local" depends="war"> - <antcall target="common.publish-local"> - <param name="conf" value="build" /> - </antcall> - </target> - - <target name="clean"> - <antcall target="common.clean" /> - </target> - <target name="checkstyle"> - <echo>Checkstyle is disabled for uitest for now</echo> - </target> - <target name="test" depends="checkstyle"> - <!--<antcall target="common.test.run" />--> - <echo>WHAT? No JUnit tests for ${module.name}!</echo> - </target> +<project name="vaadin-uitest" basedir="." default="publish-local" + xmlns:ivy="antlib:org.apache.ivy.ant"> + <description> + Provides a uitest WAR containing Vaadin UI tests + </description> + <include file="../common.xml" as="common" /> + <include file="../build.xml" as="vaadin" /> + + <!-- global properties --> + <property name="module.name" value="vaadin-uitest" /> + <property name="result.dir" value="result" /> + <property name="result.war" + location="${result.dir}/lib/${module.name}-${vaadin.version}.war" /> + + <path id="classpath.compile.custom"> + </path> + + <target name="dependencies"> + <!-- This is copied from common.xml to be able to add server.test.source + to the source path --> + + <ivy:resolve resolveid="common" conf="build, build-provided" /> + <ivy:cachepath pathid="classpath.compile.dependencies" + conf="build, build-provided" /> + </target> + + <target name="compile" description="Compiles the module" + depends="dependencies"> + + <fail unless="module.name" message="No module name given" /> + <property name="result.dir" location="result" /> + <property name="src" location="${result.dir}/../src" /> + <property name="classes" location="${result.dir}/classes" /> + <property name="server.test.sources" location="${result.dir}/../../server/tests/src" /> + <mkdir dir="${classes}" /> + + <!-- TODO: Get rid of this --> + <javac destdir="${classes}" source="${vaadin.java.version}" + target="${vaadin.java.version}" debug="true" encoding="UTF-8" + includeantruntime="false"> + <src path="${server.test.sources}" /> + <include name="com/vaadin/tests/data/bean/**" /> + <include name="com/vaadin/tests/VaadinClasses.java" /> + <include + name="com/vaadin/data/util/sqlcontainer/SQLTestsConstants.java" /> + <classpath refid="classpath.compile.dependencies" /> + <classpath refid="classpath.compile.custom" /> + </javac> + + <javac destdir="${classes}" source="${vaadin.java.version}" + target="${vaadin.java.version}" debug="true" encoding="UTF-8" + includeantruntime="false"> + <src path="${src}" /> + <classpath location="${classes}" /> + <classpath refid="classpath.compile.dependencies" /> + <classpath refid="classpath.compile.custom" /> + </javac> + </target> + + <target name="testing-widgetset" depends="dependencies,compile"> + <property name="module" + value="com.vaadin.tests.widgetset.TestingWidgetSet" /> + <property name="style" value="OBF" /> + <property name="localWorkers" value="2" /> + <property name="extraParams" value="" /> + <property name="module.output.dir" location="${result.dir}/VAADIN/widgetsets" /> + <property name="work.dir" location="${result.dir}/work" /> + + <mkdir dir="${module.output.dir}" /> + + <echo>Compiling ${module} to ${module.output.dir}</echo> + + <!-- compile the module --> + <java classname="com.google.gwt.dev.Compiler" classpathref="classpath.compile.dependencies" + failonerror="yes" fork="yes" maxmemory="512m"> + <classpath location="src" /> + <classpath location="${classes}" /> + <arg value="-workDir" /> + <arg value="${work.dir}" /> + <arg value="-logLevel" /> + <arg value="TRACE" /> + <arg value="-war" /> + <arg value="${module.output.dir}" /> + <arg value="-style" /> + <arg value="${style}" /> + + <arg value="-localWorkers" /> + <arg value="${localWorkers}" /> + <arg value="-strict" /> + <arg line="${extraParams}" /> + <arg value="${module}" /> + + <sysproperty key="vFailIfNotSerializable" value="true" /> + + <jvmarg value="-Xss8M" /> + <jvmarg value="-XX:MaxPermSize=256M" /> + <jvmarg value="-Djava.awt.headless=true" /> + </java> + + </target> + + <target name="war" depends="dependencies, compile, testing-widgetset"> + <property name="result.dir" location="result" /> + <property name="classes" location="${result.dir}/classes" /> + <property name="WebContent.dir" location="${vaadin.basedir}/WebContent" /> + <property name="deps.dir" location="${result.dir}/deps" /> + <property name="src" location="${result.dir}/../src" /> + + <ivy:resolve resolveid="common" conf="build" /> + <ivy:cachepath pathid="classpath.runtime.dependencies" + conf="build" /> + + <delete dir="${deps.dir}" /> + <mkdir dir="${deps.dir}" /> + + <copy todir="${deps.dir}" flatten="true"> + <path refid="classpath.runtime.dependencies" /> + </copy> + + + <!-- Ensure filtered webcontent files are available --> + <antcall target="common.filter.webcontent" /> + + <war destfile="${result.war}" duplicate="fail" index="true"> + <fileset refid="common.files.for.all.jars" /> + <fileset dir="${result.dir}"> + <include name="VAADIN/widgetsets/**/*" /> + </fileset> + <fileset dir="${WebContent.dir}"> + <include name="statictestfiles/**" /> + <include name="VAADIN/themes/tests-*/**" /> + <include name="VAADIN/themes/reindeer-tests/**" /> + <include name="WEB-INF/*.xml" /> + </fileset> + <classes dir="${classes}" /> + <classes dir="${src}" /> + <lib dir="${deps.dir}" /> + </war> + + </target> + + <target name="publish-local" depends="war"> + <antcall target="common.publish-local"> + <param name="conf" value="build" /> + </antcall> + </target> + + <target name="clean"> + <antcall target="common.clean" /> + </target> + <target name="checkstyle"> + <echo>Checkstyle is disabled for uitest for now</echo> + </target> + <target name="test" depends="checkstyle"> + <!--<antcall target="common.test.run" /> --> + <echo>WHAT? No JUnit tests for ${module.name}!</echo> + </target> </project>
\ No newline at end of file diff --git a/uitest/integration_base_files/base.xml b/uitest/integration_base_files/base.xml index 5196aecfa9..d8ba018b75 100644 --- a/uitest/integration_base_files/base.xml +++ b/uitest/integration_base_files/base.xml @@ -1,138 +1,143 @@ <?xml version="1.0"?> <project name="test" basedir="."> - <property file="deploy.properties" /> + <property file="deploy.properties" /> <property name="lock" value="deploy/lock.file" /> <property name="deployDir" value="deploy/${server}" /> <property name="serverPort" value="8080" /> <property name="war" value="demo.war" /> <property name="startupSpawn" value="false" /> <property name="JAVA_HOME" value="/usr/lib/jvm/default-java" /> - <property name="waitMinutes" value="3" /> - <property name="waitUrl" value="http://localhost:${serverPort}/demo/VAADIN/themes/reindeer/styles.css" /> - <property name="shutdownWait" value="10" /> + <property name="waitMinutes" value="3" /> + <property name="waitUrl" + value="http://localhost:${serverPort}/demo/VAADIN/themes/reindeer/styles.css" /> + <property name="shutdownWait" value="10" /> + - <target name="afterDeploy"> - <!-- Empty default --> + <!-- Empty default --> </target> - + <target name="beforeDeploy"> - <!-- Empty default --> + <!-- Empty default --> + </target> + + <target name="deploy"> + <antcall target="beforeDeploy" /> + <echo + message="${server}: Deploying ${war} to ${deployDir}/${autodeployDir}" /> + <copy file="${war}" todir="${deployDir}/${autodeployDir}" /> + <antcall target="afterDeploy" /> + </target> + + <target name="deployStatic"> + <unzip src="${war}" dest="${staticDeployDir}/tmp-unpack-jar/"> + <patternset> + <include name="WEB-INF/lib/*.jar" /> + </patternset> + </unzip> + <unzip dest="${staticDeployDir}"> + <fileset dir="${staticDeployDir}/tmp-unpack-jar/WEB-INF/lib" + includes="*.jar" /> + + <patternset> + <include name="VAADIN/**" /> + </patternset> + </unzip> + <delete dir="${staticDeployDir}/tmp-unpack-jar/" /> + + <unzip src="${war}" dest="${staticDeployDir}"> + <patternset> + <include name="VAADIN/**" /> + </patternset> + </unzip> + </target> + + <target name="unpack-server"> + <echo message="${server}: Unpacking ${server}.tar.gz" /> + <delete dir="${server}" /> + <exec executable="tar"> + <arg value="-xf" /> + <arg value="${server}.tar.gz" /> + </exec> + <move file="${server}" tofile="${deployDir}" /> + <echo message="Done." /> + </target> + + <target name="doStartup"> + <exec executable="./run.sh" spawn="${startupSpawn}"> + <env key="JAVA_HOME" value="${JAVA_HOME}" /> + </exec> + </target> + + <target name="startup"> + <antcall target="doStartup" /> + <echo message="${server}: Waiting for ${waitUrl} to become available." /> + <waitfor maxwait="${waitMinutes}" maxwaitunit="minute" + checkevery="10000" timeoutproperty="timeout"> + <http url="${waitUrl}" /> + </waitfor> + <!-- Print load averages to get an indicator on whether the server + still attempts to start up --> + <exec executable="uptime" /> + <fail if="timeout" message="${server} failed to deploy" /> + + <echo message="${server}: Demo deployed successfully." /> + </target> + + <target name="shutdown"> + <exec executable="./stop.sh"> + <env key="JAVA_HOME" value="${JAVA_HOME}" /> + </exec> + <sleep seconds="${shutdownWait}" /> + </target> + + <target name="force-shutdown"> + <exec executable="./cleanup.sh" /> + </target> + + <target name="check-port"> + <fail + message="${server}: Something is still listening on port ${serverPort}"> + <condition> + <socket server="localhost" port="${serverPort}" /> + </condition> + </fail> + </target> + + <target name="check-lock"> + <available file="${lock}" property="lockAvailable" /> + <fail unless="lockAvailable" message="Instance is not locked!" /> + </target> + + <target name="get-lock"> + <mkdir dir="deploy" /> + <echo>${server}: Getting the lock</echo> + <exec executable="lockfile" failonerror="true"> + <!-- Check every 10 seconds --> + <arg value="-10" /> + <!-- Retry for 55 minutes (build server gives up after 60 minutes) --> + <arg value="-r330" /> + <arg value="${lock}" /> + </exec> + <echo>${server}: Got the lock</echo> + </target> + + <target name="clean"> + <delete dir="${deployDir}" failonerror="false" /> + </target> + + <target name="release-lock"> + <!-- <exec executable="rm"> <arg value="-f" /> <arg value="${lock}" + /> </exec> --> + <delete> + <fileset dir="." includes="${lock}" /> + </delete> + <echo>${server}: Released the lock</echo> </target> - - <target name="deploy"> - <antcall target="beforeDeploy" /> - <echo message="${server}: Deploying ${war} to ${deployDir}/${autodeployDir}" /> - <copy file="${war}" todir="${deployDir}/${autodeployDir}"/> - <antcall target="afterDeploy" /> - </target> - - <target name="deployStatic"> - <unzip src="${war}" dest="${staticDeployDir}/tmp-unpack-jar/"> - <patternset> - <include name="WEB-INF/lib/*.jar" /> - </patternset> - </unzip> - <unzip dest="${staticDeployDir}"> - <fileset dir="${staticDeployDir}/tmp-unpack-jar/WEB-INF/lib" includes="*.jar" /> - - <patternset> - <include name="VAADIN/**" /> - </patternset> - </unzip> - <delete dir="${staticDeployDir}/tmp-unpack-jar/" /> - - <unzip src="${war}" dest="${staticDeployDir}"> - <patternset> - <include name="VAADIN/**" /> - </patternset> - </unzip> - </target> - - <target name="unpack-server"> - <echo message="${server}: Unpacking ${server}.tar.gz" /> - <delete dir="${server}" /> - <exec executable="tar"> - <arg value="-xf"/> - <arg value="${server}.tar.gz"/> - </exec> - <move file="${server}" tofile="${deployDir}" /> - <echo message="Done." /> - </target> - - <target name="doStartup"> - <exec executable="./run.sh" spawn="${startupSpawn}"> - <env key="JAVA_HOME" value="${JAVA_HOME}" /> - </exec> - </target> - - <target name="startup"> - <antcall target="doStartup" /> - <echo message="${server}: Waiting for ${waitUrl} to become available." /> - <waitfor maxwait="${waitMinutes}" maxwaitunit="minute" checkevery="10000" timeoutproperty="timeout"> - <http url="${waitUrl}" /> - </waitfor> - <!-- Print load averages to get an indicator on whether the server still attempts to start up --> - <exec executable="uptime" /> - <fail if="timeout" message="${server} failed to deploy" /> - - <echo message="${server}: Demo deployed successfully." /> - </target> - - <target name="shutdown"> - <exec executable="./stop.sh" > - <env key="JAVA_HOME" value="${JAVA_HOME}" /> - </exec> - <sleep seconds="${shutdownWait}" /> - </target> - - <target name="force-shutdown"> - <exec executable="./cleanup.sh" /> - </target> - - <target name="check-port"> - <fail message="${server}: Something is still listening on port ${serverPort}"> - <condition> - <socket server="localhost" port="${serverPort}" /> - </condition> - </fail> - </target> - - <target name="check-lock"> - <available file="${lock}" property="lockAvailable" /> - <fail unless="lockAvailable" message="Instance is not locked!" /> - </target> - - <target name="get-lock"> - <mkdir dir="deploy" /> - <echo>${server}: Getting the lock</echo> - <exec executable="lockfile" failonerror="true"> - <!-- Check every 10 seconds --> - <arg value="-10" /> - <!-- Retry for 55 minutes (build server gives up after 60 minutes) --> - <arg value="-r330" /> - <arg value="${lock}" /> - </exec> - <echo>${server}: Got the lock</echo> - </target> - - <target name="clean"> - <delete dir="${deployDir}" failonerror="false" /> - </target> - - <target name="release-lock"> -<!-- <exec executable="rm"> - <arg value="-f" /> - <arg value="${lock}" /> - </exec> --> - <delete> - <fileset dir="." includes="${lock}" /> - </delete> - <echo>${server}: Released the lock</echo> - </target> - - <target name="startup-and-deploy" depends="check-lock,check-port,unpack-server,deploy,startup" /> - - <target name="shutdown-and-cleanup" depends="shutdown,clean,release-lock,force-shutdown" /> - + + <target name="startup-and-deploy" + depends="check-lock,check-port,unpack-server,deploy,startup" /> + + <target name="shutdown-and-cleanup" depends="shutdown,clean,release-lock,force-shutdown" /> + </project> diff --git a/uitest/integration_tests.xml b/uitest/integration_tests.xml index cb96834307..ba353dbdbb 100644 --- a/uitest/integration_tests.xml +++ b/uitest/integration_tests.xml @@ -1,541 +1,634 @@ <?xml version="1.0"?> -<project xmlns:antcontrib="antlib:net.sf.antcontrib" name="Vaadin Integration Tests" basedir="." default="integration-test-all"> - - <!-- Import common targets --> - <import file="../common.xml" /> - <dirname file="${ant.file.Vaadin Integration Tests}" property="integration_test.dir" /> - - <!-- Target deploying demo.war --> - <fail unless="test.integration.server" message="test.integration.server must be set for integration tests to run" /> - - <fail unless="test.integration.user" message="test.integration.user must be set for integration tests to run" /> - <fail unless="test.integration.antfile" message="test.integration.antfile must be set for integration tests to run" /> - - <!-- Test with these browsers --> - <property name="test_browsers" value="winxp-firefox17-esr" /> - - <!-- Path to key file. Default value --> - <property name="sshkey.file" value="id_dsa" /> - - <!-- path and name for demo.war to be deployed --> - <property name="demo.war" value="demo.war" /> - - <!-- Host running Testbench RC or Testbench Hub. Default value --> - <property name="com.vaadin.testbench.tester.host" value="127.0.0.1" /> - - <!-- Base url where the testable application is deployed --> - <property name="deployment.url" value="http://${test.integration.server}:8080" /> - - <!-- ssh host values --> - <property name="ant.hub" value="${test.integration.antfile}" /> - <property name="user" value="${test.integration.user}" /> - <property name="passphrase" value="" /> - - <!-- Upload war to deploy to ssh host --> - <target name="integration-test-upload-demo"> - <scp file="${demo.war}" todir="${user}@${test.integration.server}:integration-tests/servers/demo.war" keyfile="${sshkey.file}" passphrase="${passphrase}" /> - </target> - - <!-- Run basic integration test test --> - <target name="integration-test-servlet"> - <fileset dir="integration-testscripts" id="html-test-files" includes="integration-test-${server-name}-servlet.html" /> - <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> - <subant target="run-tests" failonerror="false" antfile="test.xml"> - <property name="com.vaadin.testbench.lib.dir" value="${com.vaadin.testbench.lib.dir}" /> - <property name="com.vaadin.testbench.tester.host" value="${com.vaadin.testbench.tester.host}" /> - <property name="com.vaadin.testbench.deployment.url" value="${deployment.url}" /> - <property name="server.start.succeeded" value="1" /> - <property name="browsers" value="${test_browsers}" /> - <property name="testfiles" value="${testfiles}" /> - <property name="test-output-dir" value="${integration_test.dir}/result/integration-test-output/${server-name}" /> - <property name="retries" value="0" /> - - <fileset dir="." includes="test.xml" /> - </subant> - </target> - - <target name="integration-test-push-servlet"> - <fileset dir="integration-testscripts" id="html-test-files" includes="integration-test-${server-name}-push-servlet.html" /> - <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> - <subant target="run-tests" failonerror="false" antfile="test.xml"> - <property name="com.vaadin.testbench.lib.dir" value="${com.vaadin.testbench.lib.dir}" /> - <property name="com.vaadin.testbench.tester.host" value="${com.vaadin.testbench.tester.host}" /> - <property name="com.vaadin.testbench.deployment.url" value="${deployment.url}" /> - <property name="server.start.succeeded" value="1" /> - <property name="browsers" value="${test_browsers}" /> - <property name="testfiles" value="${testfiles}" /> - <property name="test-output-dir" value="${integration_test.dir}/result/integration-test-output/${server-name}" /> - <property name="retries" value="0" /> - - <fileset dir="." includes="test.xml" /> - </subant> - </target> - - <target name="integration-test-theme"> - <subant target="run-tests" failonerror="false" antfile="test.xml"> - <property name="com.vaadin.testbench.lib.dir" value="${com.vaadin.testbench.lib.dir}" /> - <property name="com.vaadin.testbench.tester.host" value="${com.vaadin.testbench.tester.host}" /> - <property name="com.vaadin.testbench.deployment.url" value="${deployment.url}" /> - <property name="server.start.succeeded" value="1" /> - <property name="testfiles" value="${testfiles-theme}" /> - <property name="test-output-dir" value="${integration_test.dir}/result/integration-test-output/${server-name}" /> - - <fileset dir="." includes="test.xml" /> - </subant> - </target> - - <!-- Run integration test on GAE --> - <target name="integration-test-test-GAE"> - <fileset dir="integration-testscripts" id="html-test-files" includes="GoogleAppEngine/integration-test-GAE.html" /> - <pathconvert pathsep=" " property="test-GAE" refid="html-test-files" /> - - <subant target="run-tests" failonerror="false" antfile="test.xml"> - <property name="com.vaadin.testbench.lib.dir" value="${com.vaadin.testbench.lib.dir}" /> - <property name="com.vaadin.testbench.tester.host" value="${com.vaadin.testbench.tester.host}" /> - <property name="com.vaadin.testbench.deployment.url" value="http://vaadin-integration-test.appspot.com/" /> - <property name="server.start.succeeded" value="1" /> - <property name="browsers" value="${test_browsers}" /> - <property name="testfiles" value="${test-GAE}" /> - <property name="test-output-dir" value="../build/integration-test-gae-output" /> - - <fileset dir="." includes="test.xml" /> - </subant> - </target> - - <target name="integration-test-deploy-to-GAE"> - <sshexec host="${test.integration.server}" username="${user}" keyfile="${sshkey.file}" command="ant -f ${ant.hub} deploy-to-GAE" /> - </target> - - - <target name="integration-test-tomcat7"> - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="10" /> - <param name="target-server" value="tomcat7" /> - </antcall> - </target> - <target name="integration-test-tomcat5"> - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="10" /> - <param name="target-server" value="tomcat5" /> - </antcall> - </target> - - <target name="integration-test-tomcat6"> - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="10" /> - <param name="target-server" value="tomcat6" /> - </antcall> - </target> - - <target name="integration-test-jetty5"> - <antcall target="run-generic-integration-test"> - <param name="target-server" value="jetty5" /> - </antcall> - </target> - - <target name="integration-test-jetty6"> - <antcall target="run-generic-integration-test"> - <param name="target-server" value="jetty6" /> - </antcall> - </target> - - <target name="integration-test-jetty7"> - <antcall target="run-generic-integration-test"> - <param name="target-server" value="jetty7" /> - </antcall> - </target> - - <target name="integration-test-jetty8"> - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="300" /> - <param name="target-server" value="jetty8" /> - </antcall> - </target> - - <target name="integration-test-jboss4"> - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="10" /> - <param name="target-server" value="jboss4" /> - </antcall> - </target> - - <target name="integration-test-jboss5"> - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="10" /> - <param name="target-server" value="jboss5" /> - </antcall> - </target> - - <target name="integration-test-jboss6"> - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="10" /> - <param name="target-server" value="jboss6" /> - </antcall> - </target> - - <target name="integration-test-jboss7"> - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="10" /> - <param name="target-server" value="jboss7" /> - </antcall> - </target> - - <target name="integration-test-glassfish2"> - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="10" /> - <param name="target-server" value="glassfish2" /> - </antcall> - </target> - - <target name="integration-test-glassfish3"> - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="10" /> - <param name="target-server" value="glassfish3" /> - </antcall> - </target> - - - <target name="integration-test-liferay6"> - <fileset dir="integration-testscripts" id="html-test-files" includes="Liferay-6/integration-test-liferay-6.0.5.html" /> - <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> - - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="600" /> - <param name="test_browsers" value="winxp-firefox17-esr" /> - <param name="target-server" value="liferay6" /> - </antcall> - </target> - - <target name="integration-test-liferay6-theme"> - <fileset dir="integration-testscripts" id="html-test-files" includes="Liferay-6/Liferay6-and-6EE-theme-deploy.html" /> - <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> - - <fileset dir="integration-testscripts" id="html-theme-files" includes="Liferay-6/Liferay6-theme.html" /> - <pathconvert pathsep=" " property="testfiles-theme" refid="html-theme-files" /> - - - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="600" /> - <param name="test_browsers" value="winxp-firefox17-esr" /> - <param name="target-server" value="liferay6" /> - </antcall> - </target> - - <target name="integration-test-liferay5"> - <fileset dir="integration-testscripts" id="html-test-files" includes="Liferay-5/integration-test-liferay-5.2.3-portlet2.html" /> - <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> - - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="600" /> - <param name="test_browsers" value="winxp-firefox17-esr" /> - <param name="target-server" value="liferay5" /> - </antcall> - </target> - - <target name="integration-test-liferay6ee"> - <fileset dir="integration-testscripts" id="html-test-files" includes="Liferay-6EE/integration-test-liferay-6ee.html" /> - <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> - - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="600" /> - <param name="test_browsers" value="winxp-firefox17-esr" /> - <param name="target-server" value="liferay6ee" /> - </antcall> - </target> - - <target name="integration-test-liferay6ee-theme"> - <fileset dir="integration-testscripts" id="html-test-files" includes="Liferay-6/Liferay6-and-6EE-theme-deploy.html" /> - <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> - - <fileset dir="integration-testscripts" id="html-theme-files" includes="Liferay-6EE/Liferay6EE-theme.html" /> - <pathconvert pathsep=" " property="testfiles-theme" refid="html-theme-files" /> - - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="600" /> - <param name="test_browsers" value="winxp-firefox17-esr" /> - <param name="target-server" value="liferay6ee" /> - </antcall> - </target> - - <target name="integration-test-gatein3"> - <fileset dir="integration-testscripts" id="html-test-files" includes="GateIn-3/integration-test-GateIn-3.1.0-portlet2.html" /> - <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="600" /> - <param name="test_browsers" value="winxp-googlechrome21" /> - <param name="target-server" value="gatein3" /> - </antcall> - </target> - - <target name="integration-test-exo3"> - <fileset dir="integration-testscripts" id="html-test-files" includes="eXo-3/integration-test-eXo-3.0.3-portlet2.html" /> - <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="600" /> - <param name="test_browsers" value="winxp-firefox17-esr" /> - <param name="target-server" value="exo3" /> - </antcall> - </target> - - <target name="integration-test-websphere8"> - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="600" /> - <param name="target-port" value="9080" /> - <param name="target-server" value="websphere8" /> - </antcall> - </target> - - <target name="integration-test-weblogic10"> - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="600" /> - <param name="target-port" value="7001" /> - <param name="target-server" value="weblogic10" /> - </antcall> - </target> - - <target name="integration-test-weblogic12"> - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="600" /> - <param name="target-port" value="7001" /> - <param name="target-server" value="weblogic12" /> - </antcall> - </target> - - - <target name="integration-test-weblogicPortal"> - <fileset dir="integration-testscripts" id="html-test-files" includes="weblogic-portal/integration-test-WebLogic-Portal-10.3.2-portlet2.html" /> - <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> - <antcall target="run-generic-integration-test"> - <param name="startDelay" value="600" /> - <param name="target-port" value="7001" /> - <param name="target-server" value="weblogicportal" /> - </antcall> - </target> - - <target name="integration-test-GAE"> - <antcall target="integration-test-deploy-to-GAE" /> - <antcall target="integration-test-test-GAE" /> - </target> - - <!-- Upload demo, clean error screenshots and test deployment on all servers --> - <target name="integration-test-all"> - <property name="passphrase" value="${passphrase}" /> - <fail unless="sshkey.file" message="You must define an ssh.keyfile parameter" /> - <fail unless="com.vaadin.testbench.screenshot.directory" message="You must define a com.vaadin.testbench.screenshot.directory parameter" /> - <parallel> - <antcontrib:trycatch property="tried"> - <try> - <!-- Still running GAE test from the old server which requires its own lock --> - <echo message="Getting lock" /> - <antcall target="integration-test-get-lock" /> - <echo message="Got lock" /> - <antcall target="integration-test-upload-demo" /> - - <antcall target="run-integration-test"> - <param name="target-server" value="GAE" /> - </antcall> - - <antcall target="integration-test-clean" /> - <echo message="Getting lock" /> - <antcall target="integration-test-release-lock" /> - <echo message="Lock released" /> - - </try> - <catch> - <echo message="Uploading of demo.war failed. ${tried}" /> - </catch> - </antcontrib:trycatch> - <antcall target="integration-test-liferay6" /> - <antcall target="integration-test-liferay6ee" /> - <antcall target="integration-test-liferay6-theme" /> - <antcall target="integration-test-liferay6ee-theme" /> - <antcall target="integration-test-exo3" /> - <antcall target="integration-test-weblogicPortal" /> - <antcall target="integration-test-liferay5" /> - <antcall target="integration-test-weblogic10" /> - <antcall target="integration-test-weblogic12" /> - <antcall target="integration-test-gatein3" /> - <antcall target="integration-test-glassfish2" /> - <antcall target="integration-test-glassfish3" /> - <antcall target="integration-test-jboss4" /> - <antcall target="integration-test-jboss5" /> - <antcall target="integration-test-jboss6" /> - <antcall target="integration-test-jboss7" /> - <antcall target="integration-test-jetty5" /> - <antcall target="integration-test-jetty6" /> - <antcall target="integration-test-jetty7" /> - <antcall target="integration-test-jetty8" /> - <antcall target="integration-test-tomcat5" /> - <antcall target="integration-test-tomcat6" /> - <antcall target="integration-test-tomcat7" /> - <antcall target="integration-test-websphere8" /> - - </parallel> - - </target> - - <target name="do-run-generic-test"> - <property name="target-host" value="${target-server}.devnet.vaadin.com" /> - <property name="target-port" value="8080" /> - <antcontrib:if> - <isset property="startDelay" /> - <then> - <antcontrib:math result="sleepTime" datatype="int"> - <op op="rint"> - <op op="*"> - <num value="${startDelay}" /> - <op op="random" /> - </op> - </op> - </antcontrib:math> - <echo>Delaying startup of ${target-server} with ${sleepTime} seconds</echo> - <sleep seconds="${sleepTime}" /> - </then> - </antcontrib:if> - - <scp todir="${user}@${target-host}:." keyfile="${sshkey.file}" trust="yes" passphrase="${passphrase}"> - <fileset dir="integration_base_files"> - <include name="*" /> - </fileset> - </scp> - - <!-- trycatch probably not needed any more as it just fails with the original message and doesn't do anything in the finally block --> - <antcontrib:trycatch property="error_message"> - <try> - <!-- timeout in one hour (remote end should timeout in 55 minutes) --> - <sshexec host="${target-host}" outputproperty="lock-output" timeout="3600000" username="${user}" keyfile="${sshkey.file}" trust="yes" command="chmod +x *.sh; ant -f deploy.xml get-lock" /> - <antcall target="echo-prefix"> - <param name="prefix" value="${target-server}: " /> - <param name="message" value="${lock-output}" /> - </antcall> - - <scp file="${demo.war}" todir="${user}@${target-host}:demo.war" keyfile="${sshkey.file}" trust="yes" passphrase="${passphrase}" /> - - <!-- timeout in 15 minutes --> - <sshexec host="${target-host}" outputproperty="start-output" timeout="900000" username="${user}" keyfile="${sshkey.file}" trust="yes" command="ant -f deploy.xml startup-and-deploy" failonerror="false" /> - <antcall target="echo-prefix"> - <param name="prefix" value="${target-server}: " /> - <param name="message" value="${start-output}" /> - </antcall> - - <fail message="${start-output}"> - <condition> - <not> - <contains string="${start-output}" substring="Demo deployed successfully" /> - </not> - </condition> - </fail> - - <copy file="integration-testscripts/common/integration_test.tpl" tofile="integration-testscripts/integration-test-${target-server}-servlet.html" overwrite="true" /> - <antcall target="integration-test-servlet"> - <param name="server-name" value="${target-server}" /> - <param name="deployment.url" value="http://${target-host}:${target-port}" /> - </antcall> - - <!-- Run theme tests in all browsers if there's a property with the test files --> - <antcontrib:if> - <isset property="testfiles-theme" /> - <antcontrib:then> - <antcall target="integration-test-theme"> - <param name="server-name" value="${target-server}" /> - <param name="deployment.url" value="http://${target-host}:${target-port}" /> - </antcall> - </antcontrib:then> - </antcontrib:if> - - <!-- Run integration tests with push --> - <copy file="integration-testscripts/common/integration_push_test.tpl" tofile="integration-testscripts/integration-test-${target-server}-push-servlet.html" overwrite="true" /> - <antcall target="integration-test-push-servlet"> - <param name="server-name" value="${target-server}" /> - <param name="deployment.url" value="http://${target-host}:${target-port}" /> - </antcall> - - <!-- Run theme tests in all browsers if there's a property with the test files --> - <antcontrib:if> - <isset property="testfiles-theme" /> - <antcontrib:then> - <antcall target="integration-test-theme"> - <param name="server-name" value="${target-server}" /> - <param name="deployment.url" value="http://${target-host}:${target-port}" /> - </antcall> - </antcontrib:then> - </antcontrib:if> - - <!-- timeout in five minutes --> - <sshexec host="${target-host}" outputproperty="stop-output" timeout="600000" username="${user}" keyfile="${sshkey.file}" trust="yes" command="ant -f deploy.xml shutdown-and-cleanup" failonerror="false" /> - <antcall target="echo-prefix"> - <param name="prefix" value="${target-server}: " /> - <param name="message" value="${stop-output}" /> - </antcall> - </try> - <catch> - <fail message="${error_message}" /> - </catch> - </antcontrib:trycatch> - </target> - - <target name="echo-prefix"> - <antcontrib:propertyregex property="message-prefixed" input="${prefix}${message}" regexp="\n" replace="\0${prefix}" global="true" defaultValue="${prefix}${message}" /> - <echo message="${message-prefixed}" /> - </target> - - <target name="run-generic-integration-test"> - <concat>##teamcity[testStarted name='${target-server}' flowId='${target-server}']</concat> - <antcontrib:trycatch property="tried"> - <try> - <antcall target="do-run-generic-test" /> - </try> - <catch> - <antcontrib:antcallback target="teamcity-escape" return="tried-escaped"> - <param name="returnTo" value="tried-escaped" /> - <param name="message" value="${tried}" /> - </antcontrib:antcallback> - <concat>##teamcity[testFailed name='${target-server}' flowId='${target-server}' message='Integration test for ${target-server} failed.' details='${tried-escaped}']</concat> - </catch> - </antcontrib:trycatch> - <concat>##teamcity[testFinished name='${target-server}' flowId='${target-server}']"</concat> - </target> - - <target name="teamcity-escape"> - <property name="returnTo" value="return" /> - - <!-- Should also perform other escaping (\u0085, \u2028 and \u2029) - see http://confluence.jetbrains.net/display/TCD65/Build+Script+Interaction+with+TeamCity --> - <!-- Immutable properties -> needs to create a new one every time --> - <antcontrib:propertyregex property="details-escaped1" input="${message}" regexp="['|\[\]]" replace="|\0" global="true" defaultValue="${message}" /> - <antcontrib:propertyregex property="details-escaped2" input="${details-escaped1}" regexp="\n" replace="|n" global="true" defaultValue="${details-escaped1}" /> - <antcontrib:propertyregex property="details-escaped3" input="${details-escaped2}" regexp="\r" replace="|r" global="true" defaultValue="${details-escaped2}" /> - - <property name="${returnTo}" value="${details-escaped3}" /> - </target> - - <target name="run-integration-test"> - <concat>##teamcity[testStarted name='${target-server}' flowId='${target-server}']</concat> - <antcontrib:trycatch property="tried"> - <try> - <antcall target="integration-test-${target-server}" /> - </try> - <catch> - <antcallback target="teamcity-escape" return="tried-escaped"> - <param name="returnTo" value="tried-escaped" /> - <param name="message" value="${tried}" /> - </antcallback> - <concat>##teamcity[testFailed name='${target-server}' flowId='${target-server}' message='Integration test for ${target-server} failed.' details='${tried-escaped}']"</concat> - </catch> - </antcontrib:trycatch> - <concat>##teamcity[testFinished name='${target-server}' flowId='${target-server}']"</concat> - </target> - - <target name="integration-test-get-lock"> - <sshexec host="${test.integration.server}" username="${user}" keyfile="${sshkey.file}" command="ant -f ${ant.hub} get-lock" /> - </target> - - <target name="integration-test-release-lock"> - <sshexec host="${test.integration.server}" username="${user}" keyfile="${sshkey.file}" command="ant -f ${ant.hub} release-lock" /> - </target> - - <!-- Remove demo.war --> - <target name="integration-test-clean"> - <sshexec host="${test.integration.server}" username="${user}" keyfile="${sshkey.file}" command="ant -f ${ant.hub} clean" /> - </target> +<project xmlns:antcontrib="antlib:net.sf.antcontrib" name="Vaadin Integration Tests" + basedir="." default="integration-test-all"> + + <!-- Import common targets --> + <import file="../common.xml" /> + <dirname file="${ant.file.Vaadin Integration Tests}" + property="integration_test.dir" /> + + <!-- Target deploying demo.war --> + <fail unless="test.integration.server" + message="test.integration.server must be set for integration tests to run" /> + + <fail unless="test.integration.user" + message="test.integration.user must be set for integration tests to run" /> + <fail unless="test.integration.antfile" + message="test.integration.antfile must be set for integration tests to run" /> + + <!-- Test with these browsers --> + <property name="test_browsers" value="winxp-firefox17-esr" /> + + <!-- Path to key file. Default value --> + <property name="sshkey.file" value="id_dsa" /> + + <!-- path and name for demo.war to be deployed --> + <property name="demo.war" value="demo.war" /> + + <!-- Host running Testbench RC or Testbench Hub. Default value --> + <property name="com.vaadin.testbench.tester.host" value="127.0.0.1" /> + + <!-- Base url where the testable application is deployed --> + <property name="deployment.url" value="http://${test.integration.server}:8080" /> + + <!-- ssh host values --> + <property name="ant.hub" value="${test.integration.antfile}" /> + <property name="user" value="${test.integration.user}" /> + <property name="passphrase" value="" /> + + <!-- Upload war to deploy to ssh host --> + <target name="integration-test-upload-demo"> + <scp file="${demo.war}" + todir="${user}@${test.integration.server}:integration-tests/servers/demo.war" + keyfile="${sshkey.file}" passphrase="${passphrase}" /> + </target> + + <!-- Run basic integration test test --> + <target name="integration-test-servlet"> + <fileset dir="integration-testscripts" id="html-test-files" + includes="integration-test-${server-name}-servlet.html" /> + <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> + <subant target="run-tests" failonerror="false" antfile="test.xml"> + <property name="com.vaadin.testbench.lib.dir" + value="${com.vaadin.testbench.lib.dir}" /> + <property name="com.vaadin.testbench.tester.host" + value="${com.vaadin.testbench.tester.host}" /> + <property name="com.vaadin.testbench.deployment.url" + value="${deployment.url}" /> + <property name="server.start.succeeded" value="1" /> + <property name="browsers" value="${test_browsers}" /> + <property name="testfiles" value="${testfiles}" /> + <property name="test-output-dir" + value="${integration_test.dir}/result/integration-test-output/${server-name}" /> + <property name="retries" value="0" /> + + <fileset dir="." includes="test.xml" /> + </subant> + </target> + + <target name="integration-test-push-servlet"> + <fileset dir="integration-testscripts" id="html-test-files" + includes="integration-test-${server-name}-push-servlet.html" /> + <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> + <subant target="run-tests" failonerror="false" antfile="test.xml"> + <property name="com.vaadin.testbench.lib.dir" + value="${com.vaadin.testbench.lib.dir}" /> + <property name="com.vaadin.testbench.tester.host" + value="${com.vaadin.testbench.tester.host}" /> + <property name="com.vaadin.testbench.deployment.url" + value="${deployment.url}" /> + <property name="server.start.succeeded" value="1" /> + <property name="browsers" value="${test_browsers}" /> + <property name="testfiles" value="${testfiles}" /> + <property name="test-output-dir" + value="${integration_test.dir}/result/integration-test-output/${server-name}" /> + <property name="retries" value="0" /> + + <fileset dir="." includes="test.xml" /> + </subant> + </target> + + <target name="integration-test-theme"> + <subant target="run-tests" failonerror="false" antfile="test.xml"> + <property name="com.vaadin.testbench.lib.dir" + value="${com.vaadin.testbench.lib.dir}" /> + <property name="com.vaadin.testbench.tester.host" + value="${com.vaadin.testbench.tester.host}" /> + <property name="com.vaadin.testbench.deployment.url" + value="${deployment.url}" /> + <property name="server.start.succeeded" value="1" /> + <property name="testfiles" value="${testfiles-theme}" /> + <property name="test-output-dir" + value="${integration_test.dir}/result/integration-test-output/${server-name}" /> + + <fileset dir="." includes="test.xml" /> + </subant> + </target> + + <!-- Run integration test on GAE --> + <target name="integration-test-test-GAE"> + <fileset dir="integration-testscripts" id="html-test-files" + includes="GoogleAppEngine/integration-test-GAE.html" /> + <pathconvert pathsep=" " property="test-GAE" refid="html-test-files" /> + + <subant target="run-tests" failonerror="false" antfile="test.xml"> + <property name="com.vaadin.testbench.lib.dir" + value="${com.vaadin.testbench.lib.dir}" /> + <property name="com.vaadin.testbench.tester.host" + value="${com.vaadin.testbench.tester.host}" /> + <property name="com.vaadin.testbench.deployment.url" + value="http://vaadin-integration-test.appspot.com/" /> + <property name="server.start.succeeded" value="1" /> + <property name="browsers" value="${test_browsers}" /> + <property name="testfiles" value="${test-GAE}" /> + <property name="test-output-dir" + value="../build/integration-test-gae-output" /> + + <fileset dir="." includes="test.xml" /> + </subant> + </target> + + <target name="integration-test-deploy-to-GAE"> + <sshexec host="${test.integration.server}" username="${user}" + keyfile="${sshkey.file}" command="ant -f ${ant.hub} deploy-to-GAE" /> + </target> + + + <target name="integration-test-tomcat7"> + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="10" /> + <param name="target-server" value="tomcat7" /> + </antcall> + </target> + <target name="integration-test-tomcat5"> + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="10" /> + <param name="target-server" value="tomcat5" /> + </antcall> + </target> + + <target name="integration-test-tomcat6"> + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="10" /> + <param name="target-server" value="tomcat6" /> + </antcall> + </target> + + <target name="integration-test-jetty5"> + <antcall target="run-generic-integration-test"> + <param name="target-server" value="jetty5" /> + </antcall> + </target> + + <target name="integration-test-jetty6"> + <antcall target="run-generic-integration-test"> + <param name="target-server" value="jetty6" /> + </antcall> + </target> + + <target name="integration-test-jetty7"> + <antcall target="run-generic-integration-test"> + <param name="target-server" value="jetty7" /> + </antcall> + </target> + + <target name="integration-test-jetty8"> + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="300" /> + <param name="target-server" value="jetty8" /> + </antcall> + </target> + + <target name="integration-test-jboss4"> + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="10" /> + <param name="target-server" value="jboss4" /> + </antcall> + </target> + + <target name="integration-test-jboss5"> + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="10" /> + <param name="target-server" value="jboss5" /> + </antcall> + </target> + + <target name="integration-test-jboss6"> + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="10" /> + <param name="target-server" value="jboss6" /> + </antcall> + </target> + + <target name="integration-test-jboss7"> + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="10" /> + <param name="target-server" value="jboss7" /> + </antcall> + </target> + + <target name="integration-test-glassfish2"> + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="10" /> + <param name="target-server" value="glassfish2" /> + </antcall> + </target> + + <target name="integration-test-glassfish3"> + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="10" /> + <param name="target-server" value="glassfish3" /> + </antcall> + </target> + + + <target name="integration-test-liferay6"> + <fileset dir="integration-testscripts" id="html-test-files" + includes="Liferay-6/integration-test-liferay-6.0.5.html" /> + <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> + + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="600" /> + <param name="test_browsers" value="winxp-firefox17-esr" /> + <param name="target-server" value="liferay6" /> + </antcall> + </target> + + <target name="integration-test-liferay6-theme"> + <fileset dir="integration-testscripts" id="html-test-files" + includes="Liferay-6/Liferay6-and-6EE-theme-deploy.html" /> + <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> + + <fileset dir="integration-testscripts" id="html-theme-files" + includes="Liferay-6/Liferay6-theme.html" /> + <pathconvert pathsep=" " property="testfiles-theme" + refid="html-theme-files" /> + + + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="600" /> + <param name="test_browsers" value="winxp-firefox17-esr" /> + <param name="target-server" value="liferay6" /> + </antcall> + </target> + + <target name="integration-test-liferay5"> + <fileset dir="integration-testscripts" id="html-test-files" + includes="Liferay-5/integration-test-liferay-5.2.3-portlet2.html" /> + <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> + + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="600" /> + <param name="test_browsers" value="winxp-firefox17-esr" /> + <param name="target-server" value="liferay5" /> + </antcall> + </target> + + <target name="integration-test-liferay6ee"> + <fileset dir="integration-testscripts" id="html-test-files" + includes="Liferay-6EE/integration-test-liferay-6ee.html" /> + <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> + + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="600" /> + <param name="test_browsers" value="winxp-firefox17-esr" /> + <param name="target-server" value="liferay6ee" /> + </antcall> + </target> + + <target name="integration-test-liferay6ee-theme"> + <fileset dir="integration-testscripts" id="html-test-files" + includes="Liferay-6/Liferay6-and-6EE-theme-deploy.html" /> + <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> + + <fileset dir="integration-testscripts" id="html-theme-files" + includes="Liferay-6EE/Liferay6EE-theme.html" /> + <pathconvert pathsep=" " property="testfiles-theme" + refid="html-theme-files" /> + + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="600" /> + <param name="test_browsers" value="winxp-firefox17-esr" /> + <param name="target-server" value="liferay6ee" /> + </antcall> + </target> + + <target name="integration-test-gatein3"> + <fileset dir="integration-testscripts" id="html-test-files" + includes="GateIn-3/integration-test-GateIn-3.1.0-portlet2.html" /> + <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="600" /> + <param name="test_browsers" value="winxp-googlechrome21" /> + <param name="target-server" value="gatein3" /> + </antcall> + </target> + + <target name="integration-test-exo3"> + <fileset dir="integration-testscripts" id="html-test-files" + includes="eXo-3/integration-test-eXo-3.0.3-portlet2.html" /> + <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="600" /> + <param name="test_browsers" value="winxp-firefox17-esr" /> + <param name="target-server" value="exo3" /> + </antcall> + </target> + + <target name="integration-test-websphere8"> + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="600" /> + <param name="target-port" value="9080" /> + <param name="target-server" value="websphere8" /> + </antcall> + </target> + + <target name="integration-test-weblogic10"> + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="600" /> + <param name="target-port" value="7001" /> + <param name="target-server" value="weblogic10" /> + </antcall> + </target> + + <target name="integration-test-weblogic12"> + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="600" /> + <param name="target-port" value="7001" /> + <param name="target-server" value="weblogic12" /> + </antcall> + </target> + + + <target name="integration-test-weblogicPortal"> + <fileset dir="integration-testscripts" id="html-test-files" + includes="weblogic-portal/integration-test-WebLogic-Portal-10.3.2-portlet2.html" /> + <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> + <antcall target="run-generic-integration-test"> + <param name="startDelay" value="600" /> + <param name="target-port" value="7001" /> + <param name="target-server" value="weblogicportal" /> + </antcall> + </target> + + <target name="integration-test-GAE"> + <antcall target="integration-test-deploy-to-GAE" /> + <antcall target="integration-test-test-GAE" /> + </target> + + <!-- Upload demo, clean error screenshots and test deployment on all + servers --> + <target name="integration-test-all"> + <property name="passphrase" value="${passphrase}" /> + <fail unless="sshkey.file" message="You must define an ssh.keyfile parameter" /> + <fail unless="com.vaadin.testbench.screenshot.directory" + message="You must define a com.vaadin.testbench.screenshot.directory parameter" /> + <parallel> + <antcontrib:trycatch property="tried"> + <try> + <!-- Still running GAE test from the old server which + requires its own lock --> + <echo message="Getting lock" /> + <antcall target="integration-test-get-lock" /> + <echo message="Got lock" /> + <antcall target="integration-test-upload-demo" /> + + <antcall target="run-integration-test"> + <param name="target-server" value="GAE" /> + </antcall> + + <antcall target="integration-test-clean" /> + <echo message="Getting lock" /> + <antcall target="integration-test-release-lock" /> + <echo message="Lock released" /> + + </try> + <catch> + <echo message="Uploading of demo.war failed. ${tried}" /> + </catch> + </antcontrib:trycatch> + <antcall target="integration-test-liferay6" /> + <antcall target="integration-test-liferay6ee" /> + <antcall target="integration-test-liferay6-theme" /> + <antcall target="integration-test-liferay6ee-theme" /> + <antcall target="integration-test-exo3" /> + <antcall target="integration-test-weblogicPortal" /> + <antcall target="integration-test-liferay5" /> + <antcall target="integration-test-weblogic10" /> + <antcall target="integration-test-weblogic12" /> + <antcall target="integration-test-gatein3" /> + <antcall target="integration-test-glassfish2" /> + <antcall target="integration-test-glassfish3" /> + <antcall target="integration-test-jboss4" /> + <antcall target="integration-test-jboss5" /> + <antcall target="integration-test-jboss6" /> + <antcall target="integration-test-jboss7" /> + <antcall target="integration-test-jetty5" /> + <antcall target="integration-test-jetty6" /> + <antcall target="integration-test-jetty7" /> + <antcall target="integration-test-jetty8" /> + <antcall target="integration-test-tomcat5" /> + <antcall target="integration-test-tomcat6" /> + <antcall target="integration-test-tomcat7" /> + <antcall target="integration-test-websphere8" /> + + </parallel> + + </target> + + <target name="do-run-generic-test"> + <property name="target-host" value="${target-server}.devnet.vaadin.com" /> + <property name="target-port" value="8080" /> + <antcontrib:if> + <isset property="startDelay" /> + <then> + <antcontrib:math result="sleepTime" + datatype="int"> + <op op="rint"> + <op op="*"> + <num value="${startDelay}" /> + <op op="random" /> + </op> + </op> + </antcontrib:math> + <echo>Delaying startup of ${target-server} with + ${sleepTime} seconds</echo> + <sleep seconds="${sleepTime}" /> + </then> + </antcontrib:if> + + <scp todir="${user}@${target-host}:." keyfile="${sshkey.file}" + trust="yes" passphrase="${passphrase}"> + <fileset dir="integration_base_files"> + <include name="*" /> + </fileset> + </scp> + + <!-- trycatch probably not needed any more as it just fails with + the original message and doesn't do anything in the finally block --> + <antcontrib:trycatch property="error_message"> + <try> + <!-- timeout in one hour (remote end should timeout in 55 + minutes) --> + <sshexec host="${target-host}" outputproperty="lock-output" + timeout="3600000" username="${user}" keyfile="${sshkey.file}" + trust="yes" command="chmod +x *.sh; ant -f deploy.xml get-lock" /> + <antcall target="echo-prefix"> + <param name="prefix" value="${target-server}: " /> + <param name="message" value="${lock-output}" /> + </antcall> + + <scp file="${demo.war}" todir="${user}@${target-host}:demo.war" + keyfile="${sshkey.file}" trust="yes" passphrase="${passphrase}" /> + + <!-- timeout in 15 minutes --> + <sshexec host="${target-host}" outputproperty="start-output" + timeout="900000" username="${user}" keyfile="${sshkey.file}" + trust="yes" command="ant -f deploy.xml startup-and-deploy" + failonerror="false" /> + <antcall target="echo-prefix"> + <param name="prefix" value="${target-server}: " /> + <param name="message" value="${start-output}" /> + </antcall> + + <fail message="${start-output}"> + <condition> + <not> + <contains string="${start-output}" + substring="Demo deployed successfully" /> + </not> + </condition> + </fail> + + <copy + file="integration-testscripts/common/integration_test.tpl" + tofile="integration-testscripts/integration-test-${target-server}-servlet.html" + overwrite="true" /> + <antcall target="integration-test-servlet"> + <param name="server-name" value="${target-server}" /> + <param name="deployment.url" + value="http://${target-host}:${target-port}" /> + </antcall> + + <!-- Run theme tests in all browsers if there's a property + with the test files --> + <antcontrib:if> + <isset property="testfiles-theme" /> + <antcontrib:then> + <antcall target="integration-test-theme"> + <param name="server-name" value="${target-server}" /> + <param name="deployment.url" + value="http://${target-host}:${target-port}" /> + </antcall> + </antcontrib:then> + </antcontrib:if> + + <!-- Run integration tests with push --> + <copy + file="integration-testscripts/common/integration_push_test.tpl" + tofile="integration-testscripts/integration-test-${target-server}-push-servlet.html" + overwrite="true" /> + <antcall target="integration-test-push-servlet"> + <param name="server-name" value="${target-server}" /> + <param name="deployment.url" + value="http://${target-host}:${target-port}" /> + </antcall> + + <!-- Run theme tests in all browsers if there's a property + with the test files --> + <antcontrib:if> + <isset property="testfiles-theme" /> + <antcontrib:then> + <antcall target="integration-test-theme"> + <param name="server-name" value="${target-server}" /> + <param name="deployment.url" + value="http://${target-host}:${target-port}" /> + </antcall> + </antcontrib:then> + </antcontrib:if> + + <!-- timeout in five minutes --> + <sshexec host="${target-host}" outputproperty="stop-output" + timeout="600000" username="${user}" keyfile="${sshkey.file}" + trust="yes" command="ant -f deploy.xml shutdown-and-cleanup" + failonerror="false" /> + <antcall target="echo-prefix"> + <param name="prefix" value="${target-server}: " /> + <param name="message" value="${stop-output}" /> + </antcall> + </try> + <catch> + <fail message="${error_message}" /> + </catch> + </antcontrib:trycatch> + </target> + + <target name="echo-prefix"> + <antcontrib:propertyregex property="message-prefixed" + input="${prefix}${message}" regexp="\n" replace="\0${prefix}" + global="true" defaultValue="${prefix}${message}" /> + <echo message="${message-prefixed}" /> + </target> + + <target name="run-generic-integration-test"> + <concat>##teamcity[testStarted name='${target-server}' + flowId='${target-server}']</concat> + <antcontrib:trycatch property="tried"> + <try> + <antcall target="do-run-generic-test" /> + </try> + <catch> + <antcontrib:antcallback target="teamcity-escape" + return="tried-escaped"> + <param name="returnTo" value="tried-escaped" /> + <param name="message" value="${tried}" /> + </antcontrib:antcallback> + <concat>##teamcity[testFailed name='${target-server}' + flowId='${target-server}' message='Integration test + for ${target-server} failed.' + details='${tried-escaped}']</concat> + </catch> + </antcontrib:trycatch> + <concat>##teamcity[testFinished name='${target-server}' + flowId='${target-server}']"</concat> + </target> + + <target name="teamcity-escape"> + <property name="returnTo" value="return" /> + + <!-- Should also perform other escaping (\u0085, \u2028 and \u2029) + - see http://confluence.jetbrains.net/display/TCD65/Build+Script+Interaction+with+TeamCity --> + <!-- Immutable properties -> needs to create a new one every time --> + <antcontrib:propertyregex property="details-escaped1" + input="${message}" regexp="['|\[\]]" replace="|\0" global="true" + defaultValue="${message}" /> + <antcontrib:propertyregex property="details-escaped2" + input="${details-escaped1}" regexp="\n" replace="|n" global="true" + defaultValue="${details-escaped1}" /> + <antcontrib:propertyregex property="details-escaped3" + input="${details-escaped2}" regexp="\r" replace="|r" global="true" + defaultValue="${details-escaped2}" /> + + <property name="${returnTo}" value="${details-escaped3}" /> + </target> + + <target name="run-integration-test"> + <concat>##teamcity[testStarted name='${target-server}' + flowId='${target-server}']</concat> + <antcontrib:trycatch property="tried"> + <try> + <antcall target="integration-test-${target-server}" /> + </try> + <catch> + <antcallback target="teamcity-escape" + return="tried-escaped"> + <param name="returnTo" value="tried-escaped" /> + <param name="message" value="${tried}" /> + </antcallback> + <concat>##teamcity[testFailed name='${target-server}' + flowId='${target-server}' message='Integration test + for ${target-server} failed.' + details='${tried-escaped}']"</concat> + </catch> + </antcontrib:trycatch> + <concat>##teamcity[testFinished name='${target-server}' + flowId='${target-server}']"</concat> + </target> + + <target name="integration-test-get-lock"> + <sshexec host="${test.integration.server}" username="${user}" + keyfile="${sshkey.file}" command="ant -f ${ant.hub} get-lock" /> + </target> + + <target name="integration-test-release-lock"> + <sshexec host="${test.integration.server}" username="${user}" + keyfile="${sshkey.file}" command="ant -f ${ant.hub} release-lock" /> + </target> + + <!-- Remove demo.war --> + <target name="integration-test-clean"> + <sshexec host="${test.integration.server}" username="${user}" + keyfile="${sshkey.file}" command="ant -f ${ant.hub} clean" /> + </target> </project> diff --git a/uitest/ivy.xml b/uitest/ivy.xml index bb54232852..7ff83324ae 100644 --- a/uitest/ivy.xml +++ b/uitest/ivy.xml @@ -14,8 +14,8 @@ <conf name="jetty-run" extends="build" visibility="private" /> </configurations> <publications> - <artifact type="war" ext="war"/> - </publications> + <artifact type="war" ext="war" /> + </publications> <dependencies defaultconf="build" defaultconfmapping="build,ide->default"> <!-- API DEPENDENCIES --> <dependency org="javax.portlet" name="portlet-api" @@ -40,9 +40,9 @@ rev="${vaadin.version}" conf="build->build"></dependency> <dependency org="com.vaadin" name="vaadin-themes" rev="${vaadin.version}" conf="build->build"></dependency> - <dependency org="com.vaadin" name="vaadin-push" - rev="${vaadin.version}" conf="build->build"></dependency> - + <dependency org="com.vaadin" name="vaadin-push" rev="${vaadin.version}" + conf="build->build"></dependency> + <!-- For compiling TestingWidgetSet --> <dependency org="com.vaadin" name="vaadin-client-compiler" rev="${vaadin.version}" conf="build-provided-> build"></dependency> diff --git a/uitest/src/com/vaadin/tests/applicationcontext/CloseUI.java b/uitest/src/com/vaadin/tests/applicationcontext/CloseUI.java index bec8c0a10f..c88f482a7b 100644 --- a/uitest/src/com/vaadin/tests/applicationcontext/CloseUI.java +++ b/uitest/src/com/vaadin/tests/applicationcontext/CloseUI.java @@ -119,7 +119,7 @@ public class CloseUI extends AbstractTestUI { @Override public void run() { - ui.access(new Runnable() { + ui.accessSynchronously(new Runnable() { @Override public void run() { diff --git a/uitest/src/com/vaadin/tests/applicationcontext/UIRunSafelyThread.java b/uitest/src/com/vaadin/tests/applicationcontext/UIRunSafelyThread.java index ddc0f28664..c9af2c000d 100644 --- a/uitest/src/com/vaadin/tests/applicationcontext/UIRunSafelyThread.java +++ b/uitest/src/com/vaadin/tests/applicationcontext/UIRunSafelyThread.java @@ -11,7 +11,7 @@ public abstract class UIRunSafelyThread extends Thread { @Override public void run() { - ui.access(new Runnable() { + ui.accessSynchronously(new Runnable() { @Override public void run() { diff --git a/uitest/src/com/vaadin/tests/components/AbstractComponentTestCase.java b/uitest/src/com/vaadin/tests/components/AbstractComponentTestCase.java index 81ec4a9da4..8666956bdb 100644 --- a/uitest/src/com/vaadin/tests/components/AbstractComponentTestCase.java +++ b/uitest/src/com/vaadin/tests/components/AbstractComponentTestCase.java @@ -226,6 +226,13 @@ public abstract class AbstractComponentTestCase<T extends AbstractComponent> } }; + protected Command<T, String> primaryStyleNameCommand = new Command<T, String>() { + @Override + public void execute(T c, String value, Object data) { + c.setPrimaryStyleName(value); + } + }; + @Override protected String getDescription() { return "Generic test case for " + getTestClass().getSimpleName(); diff --git a/uitest/src/com/vaadin/tests/components/calendar/CalendarDragAndDrop.html b/uitest/src/com/vaadin/tests/components/calendar/CalendarDragAndDrop.html new file mode 100644 index 0000000000..425f95c529 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/calendar/CalendarDragAndDrop.html @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="http://localhost:7171/" /> +<title>New Test</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">New Test</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.components.calendar.CalendarDragAndDrop?restartApplication</td> + <td></td> +</tr> +<!--// Test drag and drop in month view--> +<tr> + <td>drag</td> + <td>vaadin=runcomvaadintestscomponentscalendarCalendarDragAndDrop::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VHorizontalLayout[0]/Slot[1]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[9]/domChild[0]/domChild[0]</td> + <td>76,7</td> +</tr> +<tr> + <td>drop</td> + <td>vaadin=runcomvaadintestscomponentscalendarCalendarDragAndDrop::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VHorizontalLayout[0]/Slot[0]/VCalendar[0]/domChild[0]/domChild[1]/domChild[1]/domChild[0]/domChild[1]/domChild[1]/domChild[5]/domChild[0]/domChild[2]</td> + <td>54,9</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentscalendarCalendarDragAndDrop::PID_SCalendar/domChild[0]/domChild[1]/domChild[1]/domChild[0]/domChild[1]/domChild[1]/domChild[5]/domChild[0]/domChild[1]</td> + <td>12:00 AM Event 10</td> +</tr> +<!--//Test drag and drop in week view--> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentscalendarCalendarDragAndDrop::PID_SCalendar/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[1]/domChild[1]/domChild[0]/domChild[0]</td> + <td>7,85</td> +</tr> +<tr> + <td>drag</td> + <td>vaadin=runcomvaadintestscomponentscalendarCalendarDragAndDrop::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VHorizontalLayout[0]/Slot[1]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[11]/domChild[0]/domChild[0]</td> + <td>34,12</td> +</tr> +<tr> + <td>drop</td> + <td>vaadin=runcomvaadintestscomponentscalendarCalendarDragAndDrop::PID_SCalendar/domChild[0]/domChild[3]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[2]/domChild[0]/domChild[15]</td> + <td>75,9</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentscalendarCalendarDragAndDrop::PID_SCalendar/domChild[0]/domChild[3]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[2]/domChild[0]/domChild[48]/domChild[0]</td> + <td>7:30 AM: Event 13</td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/components/calendar/CalendarDragAndDrop.java b/uitest/src/com/vaadin/tests/components/calendar/CalendarDragAndDrop.java new file mode 100644 index 0000000000..7477fc84ce --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/calendar/CalendarDragAndDrop.java @@ -0,0 +1,123 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +/** + * + */ +package com.vaadin.tests.components.calendar; + +import java.util.GregorianCalendar; +import java.util.Locale; + +import com.vaadin.event.dd.DragAndDropEvent; +import com.vaadin.event.dd.DropHandler; +import com.vaadin.event.dd.acceptcriteria.AcceptAll; +import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Calendar; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Table; +import com.vaadin.ui.Table.TableDragMode; +import com.vaadin.ui.Table.TableTransferable; +import com.vaadin.ui.components.calendar.CalendarTargetDetails; +import com.vaadin.ui.components.calendar.event.BasicEvent; + +public class CalendarDragAndDrop extends AbstractTestUI { + + private Calendar calendar; + + private Table table; + + private class TestDropHandler implements DropHandler { + + @Override + public void drop(DragAndDropEvent event) { + CalendarTargetDetails details = (CalendarTargetDetails) event + .getTargetDetails(); + + TableTransferable transferable = (TableTransferable) event + .getTransferable(); + + calendar.addEvent(new BasicEvent(transferable.getItemId() + .toString(), "This event was dragged here", details + .getDropTime())); + + table.removeItem(transferable.getItemId()); + } + + @Override + public AcceptCriterion getAcceptCriterion() { + return AcceptAll.get(); + } + } + + @Override + protected void setup(VaadinRequest request) { + setSizeFull(); + getContent().setSizeFull(); + getLayout().setSizeFull(); + + HorizontalLayout root = new HorizontalLayout(); + root.setSizeFull(); + addComponent(root); + + Locale locale = new Locale("en", "US"); + GregorianCalendar cal = new GregorianCalendar(locale); + cal.set(2013, 0, 1); + + calendar = new Calendar(); + calendar.setId("Calendar"); + calendar.setLocale(locale); + calendar.setDropHandler(new TestDropHandler()); + calendar.setSizeFull(); + root.addComponent(calendar); + + calendar.setStartDate(cal.getTime()); + cal.add(java.util.Calendar.MONTH, 1); + calendar.setEndDate(cal.getTime()); + + table = new Table(); + table.setSizeFull(); + table.setDragMode(TableDragMode.ROW); + table.addGeneratedColumn("COLUMN", new Table.ColumnGenerator() { + + @Override + public Object generateCell(Table source, Object itemId, + Object columnId) { + return itemId; + } + }); + + for (int eventNum = 1; eventNum < 50; eventNum++) { + table.addItem("Event " + eventNum); + } + + root.addComponent(table); + } + + @Override + protected String getTestDescription() { + // TODO Auto-generated method stub + return null; + } + + @Override + protected Integer getTicketNumber() { + return 11048; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/datefield/CustomDateFormats.java b/uitest/src/com/vaadin/tests/components/datefield/CustomDateFormats.java index 247478256f..015a974b3e 100644 --- a/uitest/src/com/vaadin/tests/components/datefield/CustomDateFormats.java +++ b/uitest/src/com/vaadin/tests/components/datefield/CustomDateFormats.java @@ -104,6 +104,7 @@ public class CustomDateFormats extends TestBase { locale); addDateField(gridLayout, getDatePattern(locale, DateFormat.SHORT), locale); + addDateField(gridLayout, "EEE d MMMM yyyy", locale); } diff --git a/uitest/src/com/vaadin/tests/components/datefield/DateFieldLocale.java b/uitest/src/com/vaadin/tests/components/datefield/DateFieldLocale.java index 5d06895d11..a4fe2b0285 100644 --- a/uitest/src/com/vaadin/tests/components/datefield/DateFieldLocale.java +++ b/uitest/src/com/vaadin/tests/components/datefield/DateFieldLocale.java @@ -16,7 +16,7 @@ public class DateFieldLocale extends TestBase { final DateField dateField = new DateField("DateField"); dateField.setLocale(new Locale("fi", "FI")); dateField.setCaption(dateField.getLocale().toString()); - dateField.setValue(new Date()); + dateField.setValue(new Date(2013 - 1900, 7 - 1, 27)); dateField.setResolution(DateField.RESOLUTION_DAY); addComponent(new Button("Change locale", new ClickListener() { diff --git a/uitest/src/com/vaadin/tests/components/datefield/DateFieldPrimaryStyleNames.html b/uitest/src/com/vaadin/tests/components/datefield/DateFieldPrimaryStyleNames.html index 31216ed1b0..38034fd0c8 100644 --- a/uitest/src/com/vaadin/tests/components/datefield/DateFieldPrimaryStyleNames.html +++ b/uitest/src/com/vaadin/tests/components/datefield/DateFieldPrimaryStyleNames.html @@ -68,12 +68,12 @@ </tr> <tr> <td>assertCSSClass</td> - <td>//body/div[last()]/div[last()]</td> + <td>//body/div[2]/div[last()]</td> <td>my-datefield-popup</td> </tr> <tr> <td>assertCSSClass</td> - <td>//body/div[last()]/div[last()]</td> + <td>//body/div[2]/div[last()]</td> <td>my-datefield-day</td> </tr> <tr> @@ -188,12 +188,12 @@ </tr> <tr> <td>assertCSSClass</td> - <td>//body/div[last()]/div[last()]</td> + <td>//body/div[2]/div[last()]</td> <td>my-second-datefield-popup</td> </tr> <tr> <td>assertCSSClass</td> - <td>//body/div[last()]/div[last()]</td> + <td>//body/div[2]/div[last()]</td> <td>my-second-datefield-day</td> </tr> <tr> diff --git a/uitest/src/com/vaadin/tests/components/datefield/DynamicallyChangeDateRange.html b/uitest/src/com/vaadin/tests/components/datefield/DynamicallyChangeDateRange.html new file mode 100644 index 0000000000..77c610f211 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/DynamicallyChangeDateRange.html @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="http://localhost:8888/" /> +<title>New Test</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">New Test</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.components.datefield.DynamicallyChangeDateRange?restartApplication</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentsdatefieldDynamicallyChangeDateRange::/VVerticalLayout[0]/Slot[0]/VPopupCalendar[0]#popupButton</td> + <td>11,8</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>//table[@id='PID_VAADIN_POPUPCAL']/tbody/tr[2]/td/table/tbody/tr[3]/td[2]/span</td> + <td>v-datefield-calendarpanel-day-outside-range</td> +</tr> +<tr> + <td>assertNotCSSClass</td> + <td>//table[@id='PID_VAADIN_POPUPCAL']/tbody/tr[2]/td/table/tbody/tr[3]/td[3]/span</td> + <td>v-datefield-calendarpanel-day-outside-range</td> +</tr> +<tr> + <td>assertNotCSSClass</td> + <td>//table[@id='PID_VAADIN_POPUPCAL']/tbody/tr[2]/td/table/tbody/tr[4]/td[6]/span</td> + <td>v-datefield-calendarpanel-day-outside-range</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>//table[@id='PID_VAADIN_POPUPCAL']/tbody/tr[2]/td/table/tbody/tr[4]/td[7]/span</td> + <td>v-datefield-calendarpanel-day-outside-range</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentsdatefieldDynamicallyChangeDateRange::</td> + <td>201,401</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsdatefieldDynamicallyChangeDateRange::/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentsdatefieldDynamicallyChangeDateRange::/VVerticalLayout[0]/Slot[0]/VPopupCalendar[0]#popupButton</td> + <td>14,16</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>//table[@id='PID_VAADIN_POPUPCAL']/tbody/tr[2]/td/table/tbody/tr[2]/td[4]/span</td> + <td>v-datefield-calendarpanel-day-outside-range</td> +</tr> +<tr> + <td>assertNotCSSClass</td> + <td>//table[@id='PID_VAADIN_POPUPCAL']/tbody/tr[2]/td/table/tbody/tr[2]/td[5]/span</td> + <td>v-datefield-calendarpanel-day-outside-range</td> +</tr> +<tr> + <td>assertNotCSSClass</td> + <td>//table[@id='PID_VAADIN_POPUPCAL']/tbody/tr[2]/td/table/tbody/tr[5]/td[4]/span</td> + <td>v-datefield-calendarpanel-day-outside-range</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>//table[@id='PID_VAADIN_POPUPCAL']/tbody/tr[2]/td/table/tbody/tr[5]/td[5]/span</td> + <td>v-datefield-calendarpanel-day-outside-range</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentsdatefieldDynamicallyChangeDateRange::</td> + <td>237,338</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsdatefieldDynamicallyChangeDateRange::/VVerticalLayout[0]/Slot[1]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentsdatefieldDynamicallyChangeDateRange::/VVerticalLayout[0]/Slot[0]/VPopupCalendar[0]#popupButton</td> + <td>14,15</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>//table[@id='PID_VAADIN_POPUPCAL']/tbody/tr[2]/td/table/tbody/tr[3]/td[2]/span</td> + <td>v-datefield-calendarpanel-day-outside-range</td> +</tr> +<tr> + <td>assertNotCSSClass</td> + <td>//table[@id='PID_VAADIN_POPUPCAL']/tbody/tr[2]/td/table/tbody/tr[3]/td[3]/span</td> + <td>v-datefield-calendarpanel-day-outside-range</td> +</tr> +<tr> + <td>assertNotCSSClass</td> + <td>//table[@id='PID_VAADIN_POPUPCAL']/tbody/tr[2]/td/table/tbody/tr[4]/td[6]/span</td> + <td>v-datefield-calendarpanel-day-outside-range</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>//table[@id='PID_VAADIN_POPUPCAL']/tbody/tr[2]/td/table/tbody/tr[4]/td[7]/span</td> + <td>v-datefield-calendarpanel-day-outside-range</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>//table[@id='PID_VAADIN_POPUPCAL']/tbody/tr[2]/td/table/tbody/tr[3]/td[2]/span</td> + <td>v-datefield-calendarpanel-day-outside-range</td> +</tr> +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/components/datefield/DynamicallyChangeDateRange.java b/uitest/src/com/vaadin/tests/components/datefield/DynamicallyChangeDateRange.java new file mode 100644 index 0000000000..fb0fb2a546 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/DynamicallyChangeDateRange.java @@ -0,0 +1,93 @@ +package com.vaadin.tests.components.datefield; + +import java.util.Date; +import java.util.Locale; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.DateField; +import com.vaadin.ui.InlineDateField; +import com.vaadin.ui.PopupDateField; +import com.vaadin.ui.VerticalLayout; + +/** + * Main UI class + */ +@SuppressWarnings("serial") +public class DynamicallyChangeDateRange extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + setLocale(Locale.ENGLISH); + final VerticalLayout layout = new VerticalLayout(); + layout.setMargin(true); + setContent(layout); + + final PopupDateField df = new PopupDateField(); + df.setValue(new Date(2012 - 1900, 5 - 1, 12)); + setRange(df, 5); + layout.addComponent(df); + + final InlineDateField df2 = new InlineDateField(); + df2.setValue(new Date(2012 - 1900, 11 - 1, 16)); + + setRange(df2, 5); + // layout.addComponent(df2); + + Button button1 = new Button("Set Range Now+/-5d"); + button1.addClickListener(new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + setRange(df, 5); + setRange(df2, 5); + } + }); + layout.addComponent(button1); + + Button button2 = new Button("Set Range Now+/-10d"); + button2.addClickListener(new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + setRange(df, 10); + setRange(df2, 10); + } + }); + layout.addComponent(button2); + } + + /** + * @since + * @param df + * @param i + */ + private void setRange(DateField df, int days) { + df.setRangeStart(new Date(df.getValue().getTime() - days * 24 * 60 * 60 + * 1000)); + df.setRangeEnd(new Date(df.getValue().getTime() + days * 24 * 60 * 60 + * 1000)); + + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTestDescription() + */ + @Override + protected String getTestDescription() { + return "Verifies that the allowed date range can be updated dynamically"; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTicketNumber() + */ + @Override + protected Integer getTicketNumber() { + return 11940; + } + +}
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/components/popupview/PopupViewAndFragment.html b/uitest/src/com/vaadin/tests/components/popupview/PopupViewAndFragment.html new file mode 100644 index 0000000000..28af578bac --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/popupview/PopupViewAndFragment.html @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="http://localhost:8888/" /> +<title>PopupViewAndFragment</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">PopupViewAndFragment</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/PopupViewAndFragment?restartApplication#</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runPopupViewAndFragment::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/components/popupview/PopupViewAndFragment.java b/uitest/src/com/vaadin/tests/components/popupview/PopupViewAndFragment.java new file mode 100644 index 0000000000..1606b78604 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/popupview/PopupViewAndFragment.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.popupview; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Label; +import com.vaadin.ui.PopupView; + +public class PopupViewAndFragment extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + final PopupView pw = new PopupView("Open", new Label("Oh, hi")); + addComponent(pw); + + final Button button = new Button("Open and change fragment", + new Button.ClickListener() { + @Override + public void buttonClick(final ClickEvent event) { + pw.setPopupVisible(true); + getPage().setUriFragment( + String.valueOf(System.currentTimeMillis())); + } + }); + addComponent(button); + } + + @Override + protected String getTestDescription() { + return "Changing frament should not automatically close PopupView"; + } + + @Override + protected Integer getTicketNumber() { + return 10530; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarGenericTest.java b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarGenericTest.java new file mode 100644 index 0000000000..79797c60a2 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarGenericTest.java @@ -0,0 +1,55 @@ +package com.vaadin.tests.components.progressindicator; + +import java.util.LinkedHashMap; + +import com.vaadin.tests.components.abstractfield.AbstractFieldTest; +import com.vaadin.ui.ProgressBar; + +public class ProgressBarGenericTest extends AbstractFieldTest<ProgressBar> { + + private Command<ProgressBar, Boolean> indeterminate = new Command<ProgressBar, Boolean>() { + + @Override + public void execute(ProgressBar c, Boolean value, Object data) { + c.setIndeterminate(value); + } + }; + + @Override + protected Class<ProgressBar> getTestClass() { + return ProgressBar.class; + } + + @Override + protected void createActions() { + super.createActions(); + createBooleanAction("Indeterminate", CATEGORY_FEATURES, false, + indeterminate, null); + createValueSelection(CATEGORY_FEATURES); + createPrimaryStyleNameSelect(); + } + + /** + * @since + */ + protected void createPrimaryStyleNameSelect() { + LinkedHashMap<String, String> options = new LinkedHashMap<String, String>(); + String primaryStyle = getComponent().getPrimaryStyleName(); + options.put(primaryStyle, primaryStyle); + options.put(primaryStyle + "-foo", primaryStyle + "-foo"); + options.put("foo", "foo"); + createSelectAction("Primary style name", CATEGORY_DECORATIONS, options, + primaryStyle, primaryStyleNameCommand); + + } + + private void createValueSelection(String categorySelection) { + LinkedHashMap<String, Object> options = new LinkedHashMap<String, Object>(); + options.put("null", null); + for (float f = 0; f <= 1; f += 0.1) { + options.put("" + f, f); + } + createSelectAction("Value", categorySelection, options, null, + setValueCommand); + } +} diff --git a/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarPrimaryStyleName.html b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarPrimaryStyleName.html new file mode 100644 index 0000000000..92f678947a --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarPrimaryStyleName.html @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="http://localhost:8888/" /> +<title>New Test</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">New Test</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.components.progressindicator.ProgressBarGenericTest?restartApplication</td> + <td></td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::PID_StestComponent</td> + <td>v-progressbar</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::PID_StestComponent/domChild[0]</td> + <td>v-progressbar-wrapper</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::PID_StestComponent/domChild[0]/domChild[0]</td> + <td>v-progressbar-indicator</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::PID_Smenu#item0</td> + <td>36,8</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::Root/VOverlay[0]/VMenuBar[0]#item1</td> + <td>45,4</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::Root/VOverlay[1]/VMenuBar[0]#item6</td> + <td>67,10</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::Root/VOverlay[2]/VMenuBar[0]#item2</td> + <td>37,7</td> +</tr> +<tr> + <td>assertNotCSSClass</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::PID_StestComponent</td> + <td>v-progressbar</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::PID_StestComponent</td> + <td>foo</td> +</tr> +<tr> + <td>assertNotCSSClass</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::PID_StestComponent/domChild[0]</td> + <td>v-progressbar-wrapper</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::PID_StestComponent/domChild[0]</td> + <td>foo-wrapper</td> +</tr> +<tr> + <td>assertNotCSSClass</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::PID_StestComponent/domChild[0]/domChild[0]</td> + <td>v-progressbar-indicator</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::PID_StestComponent/domChild[0]/domChild[0]</td> + <td>foo-indicator</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::PID_Smenu#item0</td> + <td>20,13</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::Root/VOverlay[0]/VMenuBar[0]#item1</td> + <td>34,11</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::Root/VOverlay[1]/VMenuBar[0]#item6</td> + <td>51,4</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::Root/VOverlay[2]/VMenuBar[0]#item0</td> + <td>38,6</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::PID_StestComponent</td> + <td>v-progressbar</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::PID_StestComponent/domChild[0]</td> + <td>v-progressbar-wrapper</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarGenericTest::PID_StestComponent/domChild[0]/domChild[0]</td> + <td>v-progressbar-indicator</td> +</tr> +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarTest.html b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarTest.html new file mode 100644 index 0000000000..b7add101f9 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarTest.html @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>New Test</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">New Test</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.components.progressindicator.ProgressBarTest?restartApplication</td> + <td></td> +</tr> +<!--Add ProgressBar and wait--> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>pause</td> + <td>1000</td> + <td></td> +</tr> +<!--Text should not have changed--> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0]</td> + <td>0</td> +</tr> +<!--Add ProgressIndicator and wait--> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>pause</td> + <td>1000</td> + <td></td> +</tr> +<!--Text should have changed--> +<tr> + <td>assertNotText</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0]</td> + <td>0</td> +</tr> +<!--Stop thread right away if we get this far (would otherwise continue running until the UI is detached)--> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsprogressindicatorProgressBarTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarTest.java b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarTest.java new file mode 100644 index 0000000000..5afa874220 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarTest.java @@ -0,0 +1,125 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.tests.components.progressindicator; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Label; +import com.vaadin.ui.ProgressBar; +import com.vaadin.ui.ProgressIndicator; + +public class ProgressBarTest extends AbstractTestUI { + + private Label updatedFromBackround; + private Thread updateThread = new Thread() { + @Override + public void run() { + Runnable updateTask = new Runnable() { + @Override + public void run() { + counter++; + updateLabel(); + } + }; + + while (true) { + access(updateTask); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + break; + } + } + } + }; + private ProgressBar progressBar; + private int counter = 0; + + @Override + protected void setup(VaadinRequest request) { + updatedFromBackround = new Label(); + updatedFromBackround.setCaption("Updated from background thread"); + updateLabel(); + addComponent(updatedFromBackround); + + addComponent(new Button("Use ProgressBar", new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + useComponent(new ProgressBar()); + } + })); + + addComponent(new Button("Use ProgressIndicator", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + useComponent(new ProgressIndicator()); + } + })); + + addComponent(new Button("Stop background thread", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + stopUpdateThread(); + } + })); + updateThread.setDaemon(true); + updateThread.start(); + } + + private void useComponent(ProgressBar progressBar) { + if (this.progressBar != null) { + removeComponent(this.progressBar); + } + this.progressBar = progressBar; + addComponent(progressBar); + + counter = 0; + updateLabel(); + } + + @Override + public void detach() { + super.detach(); + stopUpdateThread(); + } + + private void stopUpdateThread() { + if (updateThread != null) { + updateThread.interrupt(); + updateThread = null; + } + } + + private void updateLabel() { + updatedFromBackround.setValue(String.valueOf(counter)); + } + + @Override + protected String getTestDescription() { + return "ProgressBar should work just as ProgressIndicator, just without the polling"; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(11925); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/richtextarea/RichTextAreaUpdateWhileTyping.html b/uitest/src/com/vaadin/tests/components/richtextarea/RichTextAreaUpdateWhileTyping.html new file mode 100644 index 0000000000..6ddd1b4097 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/richtextarea/RichTextAreaUpdateWhileTyping.html @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="http://localhost:7070/" /> +<title>New Test</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">New Test</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.components.richtextarea.RichTextAreaUpdateWhileTyping?restartApplication</td> + <td></td> +</tr> +<tr> + <td>selectFrame</td> + <td>xpath=//div[@id='rta']/iframe</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>//body</td> + <td>This text should be visible, even after an update while I type.</td> +</tr> +<tr> + <td>pause</td> + <td>2000</td> + <td></td> +</tr> +<tr> + <td>assertText</td> + <td>//body</td> + <td>This text should be visible, even after an update while I type.</td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/components/richtextarea/RichTextAreaUpdateWhileTyping.java b/uitest/src/com/vaadin/tests/components/richtextarea/RichTextAreaUpdateWhileTyping.java new file mode 100644 index 0000000000..df1d6df463 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/richtextarea/RichTextAreaUpdateWhileTyping.java @@ -0,0 +1,51 @@ +package com.vaadin.tests.components.richtextarea; + +import com.vaadin.data.Property; +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.progressindicator.ProgressIndicatorServerRpc; +import com.vaadin.tests.components.AbstractComponentTest; +import com.vaadin.tests.components.AbstractTestCase; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.ProgressIndicator; +import com.vaadin.ui.RichTextArea; + +public class RichTextAreaUpdateWhileTyping extends AbstractTestUI { + + private RichTextArea rta; + + @Override + protected void setup(VaadinRequest request) { + + // Progress indicator for changing the value of the RTA + ProgressIndicator pi = new ProgressIndicator() { + { + registerRpc(new ProgressIndicatorServerRpc() { + + @Override + public void poll() { + rta.markAsDirty(); + } + }); + } + }; + pi.setHeight("0px"); + addComponent(pi); + + rta = new RichTextArea(); + rta.setId("rta"); + rta.setImmediate(true); + addComponent(rta); + } + + @Override + protected String getTestDescription() { + // TODO Auto-generated method stub + return null; + } + + @Override + protected Integer getTicketNumber() { + return 11741; + } +} diff --git a/uitest/src/com/vaadin/tests/components/table/TableSqlContainer.html b/uitest/src/com/vaadin/tests/components/table/TableSqlContainer.html new file mode 100644 index 0000000000..96df94148c --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableSqlContainer.html @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="http://localhost:8888/" /> +<title>New Test</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">New Test</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.components.table.TableSqlContainer?restartApplication</td> + <td></td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentstableTableSqlContainer::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[1]/domChild[0]</td> + <td>May 24, 2013 12:00:00 AM</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentstableTableSqlContainer::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VCheckBox[0]/domChild[0]</td> + <td>12,7</td> +</tr> +<tr> + <td>assertValue</td> + <td>vaadin=runcomvaadintestscomponentstableTableSqlContainer::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[0]/VPopupCalendar[0]#field</td> + <td>5/24/13</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentstableTableSqlContainer::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[0]/VPopupCalendar[0]#popupButton</td> + <td>9,7</td> +</tr> +<tr> + <td>mouseClick</td> + <td>//table[@id='PID_VAADIN_POPUPCAL']/tbody/tr[2]/td/table/tbody/tr[4]/td[5]/span</td> + <td>11,10</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentstableTableSqlContainer::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VCheckBox[0]/domChild[0]</td> + <td>9,12</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentstableTableSqlContainer::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[1]/domChild[0]</td> + <td>May 15, 2013 12:00:00 AM</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentstableTableSqlContainer::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[1]/domChild[0]</td> + <td>Apr 26, 2013 12:00:00 AM</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentstableTableSqlContainer::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[1]/domChild[0]</td> + <td>May 27, 2013 12:00:00 AM</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentstableTableSqlContainer::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[3]/domChild[1]/domChild[0]</td> + <td>Apr 28, 2013 12:00:00 AM</td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/components/table/TableSqlContainer.java b/uitest/src/com/vaadin/tests/components/table/TableSqlContainer.java new file mode 100644 index 0000000000..5191b1b86e --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableSqlContainer.java @@ -0,0 +1,142 @@ +package com.vaadin.tests.components.table; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Locale; + +import com.vaadin.data.Property; +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.data.util.sqlcontainer.SQLContainer; +import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.query.TableQuery; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.CheckBox; +import com.vaadin.ui.Label; +import com.vaadin.ui.Table; +import com.vaadin.ui.VerticalLayout; + +public class TableSqlContainer extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + setLocale(Locale.ENGLISH); + VerticalLayout layout = new VerticalLayout(); + addComponent(layout); + + final Table table = new Table("Table with SQLContainer"); + layout.addComponent(table); + + final Label selectedLabel = new Label("Selected: null"); + layout.addComponent(selectedLabel); + + try { + JDBCConnectionPool connectionPool = new SimpleJDBCConnectionPool( + "org.hsqldb.jdbc.JDBCDriver", + "jdbc:hsqldb:mem:sqlcontainer", "SA", "", 2, 20); + + createTestTable(connectionPool); + insertTestData(connectionPool); + + TableQuery q = new TableQuery("mytable", connectionPool); + q.setVersionColumn("version"); + SQLContainer myContainer = new SQLContainer(q); + + table.setContainerDataSource(myContainer); + + } catch (SQLException e) { + e.printStackTrace(); + } + + table.setImmediate(true); + table.setSizeFull(); + table.setSelectable(true); + table.addValueChangeListener(new Property.ValueChangeListener() { + @Override + public void valueChange(ValueChangeEvent event) { + selectedLabel.setValue("Selected: " + + event.getProperty().getValue()); + } + }); + + final CheckBox editMode = new CheckBox("Edit mode"); + editMode.addValueChangeListener(new ValueChangeListener() { + @Override + public void valueChange(ValueChangeEvent event) { + table.setEditable(editMode.getValue()); + } + }); + addComponent(editMode); + } + + /** + * (Re)creates the test table + * + * @param connectionPool + */ + private void createTestTable(JDBCConnectionPool connectionPool) { + Connection conn = null; + try { + conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + try { + statement.executeUpdate("DROP TABLE mytable"); + } catch (SQLException e) { + } + statement.execute("CREATE TABLE mytable " + + "(id INTEGER GENERATED BY DEFAULT AS IDENTITY, D DATE," + + "MYFIELD VARCHAR(45), " + "PRIMARY KEY(ID))"); + statement.close(); + conn.commit(); + } catch (SQLException e) { + e.printStackTrace(); + } finally { + connectionPool.releaseConnection(conn); + } + } + + /** + * Adds test data to the test table + * + * @param connectionPool + * @throws SQLException + */ + private void insertTestData(JDBCConnectionPool connectionPool) + throws SQLException { + Connection conn = null; + try { + conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + + statement + .executeUpdate("INSERT INTO mytable VALUES(1, '2013-05-24', 'A0')"); + statement + .executeUpdate("INSERT INTO mytable VALUES(2, '2013-04-26', 'A1')"); + statement + .executeUpdate("INSERT INTO mytable VALUES(3, '2013-05-27', 'B0')"); + statement + .executeUpdate("INSERT INTO mytable VALUES(4, '2013-04-28', 'B1')"); + + statement.close(); + conn.commit(); + } catch (SQLException e) { + e.printStackTrace(); + } finally { + connectionPool.releaseConnection(conn); + } + } + + @Override + protected String getTestDescription() { + return "A test with Table connected to a SQLContainer using TableQuery"; + } + + @Override + protected Integer getTicketNumber() { + return 11224; + } + +}
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/components/ui/UiAccess.html b/uitest/src/com/vaadin/tests/components/ui/UiAccess.html new file mode 100644 index 0000000000..613691623c --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/ui/UiAccess.html @@ -0,0 +1,166 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>New Test</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">New Test</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.components.ui.UiAccess?restartApplication</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[0]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_2</td> + <td>exact:0. Access from UI thread future is done? false</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1</td> + <td>1. Access from UI thread is run</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0</td> + <td>exact:2. beforeClientResponse future is done? true</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[1]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1</td> + <td>0. Initial background message</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0</td> + <td>exact:1. Thread has current response? false</td> +</tr> +<tr> + <td>waitForText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_2</td> + <td>0. Initial background message</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0</td> + <td>exact:2. Thread got lock, inital future done? true</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_2</td> + <td>0. Throwing exception in access</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1</td> + <td>exact:1. firstFuture is done? true</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0</td> + <td>2. Got exception from firstFuture: java.lang.RuntimeException: Catch me if you can</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[3]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0</td> + <td>0. future was cancled, should not start</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[4]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_2</td> + <td>0. Waiting for thread to start</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1</td> + <td>1. Thread started, waiting for interruption</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0</td> + <td>2. I was interrupted</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[5]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_3</td> + <td>0. accessSynchronously has request? true</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_2</td> + <td>1. Test value in accessSynchronously: Set before accessSynchronosly</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1</td> + <td>2. has request after accessSynchronously? true</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0</td> + <td>3. Test value after accessSynchornously: Set in accessSynchronosly</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[6]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_3</td> + <td>0. access has request? false</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_2</td> + <td>1. Test value in access: Set before access</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1</td> + <td>2. has request after access? true</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0</td> + <td>3. Test value after access: Set before run pending</td> +</tr> +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/components/ui/UiAccess.java b/uitest/src/com/vaadin/tests/components/ui/UiAccess.java new file mode 100644 index 0000000000..2bc91fa7b4 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/ui/UiAccess.java @@ -0,0 +1,307 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.tests.components.ui; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.locks.ReentrantLock; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.server.VaadinService; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.util.CurrentInstance; + +public class UiAccess extends AbstractTestUIWithLog { + + private Future<Void> checkFromBeforeClientResponse; + + private class CurrentInstanceTestType { + private String value; + + public CurrentInstanceTestType(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } + } + + @Override + protected void setup(VaadinRequest request) { + addComponent(new Button("Access from UI thread", + new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + log.clear(); + // Ensure beforeClientResponse is invoked + markAsDirty(); + checkFromBeforeClientResponse = access(new Runnable() { + @Override + public void run() { + log("Access from UI thread is run"); + } + }); + log("Access from UI thread future is done? " + + checkFromBeforeClientResponse.isDone()); + } + })); + addComponent(new Button("Access from background thread", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + log.clear(); + final CountDownLatch latch = new CountDownLatch(1); + + new Thread() { + @Override + public void run() { + final boolean threadHasCurrentResponse = VaadinService + .getCurrentResponse() != null; + // session is locked by request thread at this + // point + final Future<Void> initialFuture = access(new Runnable() { + @Override + public void run() { + log("Initial background message"); + log("Thread has current response? " + + threadHasCurrentResponse); + } + }); + + // Let request thread continue + latch.countDown(); + + // Wait until thread can be locked + while (!getSession().getLockInstance() + .tryLock()) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + try { + log("Thread got lock, inital future done? " + + initialFuture.isDone()); + setPollInterval(-1); + } finally { + getSession().unlock(); + } + } + }.start(); + + // Wait for thread to do initialize before continuing + try { + latch.await(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + setPollInterval(3000); + } + })); + addComponent(new Button("Access throwing exception", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + log.clear(); + final Future<Void> firstFuture = access(new Runnable() { + @Override + public void run() { + log("Throwing exception in access"); + throw new RuntimeException( + "Catch me if you can"); + } + }); + access(new Runnable() { + @Override + public void run() { + log("firstFuture is done? " + + firstFuture.isDone()); + try { + firstFuture.get(); + log("Should not get here"); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (ExecutionException e) { + log("Got exception from firstFuture: " + + e.getMessage()); + } + } + }); + } + })); + addComponent(new Button("Cancel future before started", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + log.clear(); + Future<Void> future = access(new Runnable() { + @Override + public void run() { + log("Should not get here"); + } + }); + future.cancel(false); + log("future was cancled, should not start"); + } + })); + addComponent(new Button("Cancel running future", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + log.clear(); + final ReentrantLock interruptLock = new ReentrantLock(); + + final Future<Void> future = access(new Runnable() { + @Override + public void run() { + log("Waiting for thread to start"); + while (!interruptLock.isLocked()) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + log("Premature interruption"); + throw new RuntimeException(e); + } + } + + log("Thread started, waiting for interruption"); + try { + interruptLock.lockInterruptibly(); + } catch (InterruptedException e) { + log("I was interrupted"); + } + } + }); + + new Thread() { + @Override + public void run() { + interruptLock.lock(); + // Wait until UI thread has started waiting for + // the lock + while (!interruptLock.hasQueuedThreads()) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + future.cancel(true); + } + }.start(); + } + })); + addComponent(new Button("CurrentInstance accessSynchronously values", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + log.clear(); + // accessSynchronously should maintain values + CurrentInstance.set(CurrentInstanceTestType.class, + new CurrentInstanceTestType( + "Set before accessSynchronosly")); + accessSynchronously(new Runnable() { + @Override + public void run() { + log.log("accessSynchronously has request? " + + (VaadinService.getCurrentRequest() != null)); + log.log("Test value in accessSynchronously: " + + CurrentInstance + .get(CurrentInstanceTestType.class)); + CurrentInstance.set( + CurrentInstanceTestType.class, + new CurrentInstanceTestType( + "Set in accessSynchronosly")); + } + }); + log.log("has request after accessSynchronously? " + + (VaadinService.getCurrentRequest() != null)); + log("Test value after accessSynchornously: " + + CurrentInstance + .get(CurrentInstanceTestType.class)); + } + })); + addComponent(new Button("CurrentInstance access values", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + log.clear(); + // accessSynchronously should maintain values + CurrentInstance + .setInheritable(CurrentInstanceTestType.class, + new CurrentInstanceTestType( + "Set before access")); + access(new Runnable() { + @Override + public void run() { + log.log("access has request? " + + (VaadinService.getCurrentRequest() != null)); + log.log("Test value in access: " + + CurrentInstance + .get(CurrentInstanceTestType.class)); + CurrentInstance.setInheritable( + CurrentInstanceTestType.class, + new CurrentInstanceTestType( + "Set in access")); + } + }); + CurrentInstance.setInheritable( + CurrentInstanceTestType.class, + new CurrentInstanceTestType( + "Set before run pending")); + + getSession().getService().runPendingAccessTasks( + getSession()); + + log.log("has request after access? " + + (VaadinService.getCurrentRequest() != null)); + log("Test value after access: " + + CurrentInstance + .get(CurrentInstanceTestType.class)); + } + })); + } + + @Override + public void beforeClientResponse(boolean initial) { + if (checkFromBeforeClientResponse != null) { + log("beforeClientResponse future is done? " + + checkFromBeforeClientResponse.isDone()); + checkFromBeforeClientResponse = null; + } + } + + @Override + protected String getTestDescription() { + return "Test for various ways of using UI.access"; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(11897); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/window/TooltipInWindow.html b/uitest/src/com/vaadin/tests/components/window/TooltipInWindow.html index d734cab9ea..63e371e379 100644 --- a/uitest/src/com/vaadin/tests/components/window/TooltipInWindow.html +++ b/uitest/src/com/vaadin/tests/components/window/TooltipInWindow.html @@ -64,6 +64,22 @@ <td>vaadin=runcomvaadintestscomponentswindowTooltipInWindow::Root/VTooltip[0]/FlowPanel[0]/domChild[1]</td> <td>My tooltip</td> </tr> +<!-- Hide tooltip in Window --> +<tr> + <td>showTooltip</td> + <td>vaadin=runcomvaadintestscomponentswindowTooltipInWindow::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]</td> + <td>0,0</td> +</tr> +<tr> + <td>pause</td> + <td>1000</td> + <td></td> +</tr> +<tr> + <td>assertElementNotPresent</td> + <td>vaadin=runcomvaadintestscomponentswindowTooltipInWindow::Root/VTooltip[0]/FlowPanel[0]/domChild[1]</td> + <td></td> +</tr> </tbody></table> </body> </html> diff --git a/uitest/src/com/vaadin/tests/components/window/WindowMaximizeRestoreTest.html b/uitest/src/com/vaadin/tests/components/window/WindowMaximizeRestoreTest.html index 945564f298..dcdfa05687 100644 --- a/uitest/src/com/vaadin/tests/components/window/WindowMaximizeRestoreTest.html +++ b/uitest/src/com/vaadin/tests/components/window/WindowMaximizeRestoreTest.html @@ -162,17 +162,6 @@ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/Slot[0]/VNativeButton[0]</td> <td>43,12</td> </tr> -<!--Remove the following two commands once #11737 is fixed--> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/Slot[0]/VNativeButton[0]</td> - <td>43,12</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/Slot[0]/VNativeButton[0]</td> - <td>43,12</td> -</tr> <!--maximize window 2 content--> <tr> <td>mouseClick</td> @@ -234,6 +223,37 @@ <td></td> <td>window-1-maximized-with-doubleclick</td> </tr> +<!--Test that size and position is preserved when maximizing and restoring--> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td> + <td>8,4</td> +</tr> +<tr> + <td>dragAndDrop</td> + <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td> + <td>-200,-200</td> +</tr> +<tr> + <td>dragAndDrop</td> + <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[4]/domChild[0]</td> + <td>+100,+100</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td> + <td>6,5</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td> + <td>5,8</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>window-1-moved-maximized-restored</td> +</tr> </tbody></table> </body> </html> diff --git a/uitest/src/com/vaadin/tests/minitutorials/broadcastingmessages/Broadcaster.java b/uitest/src/com/vaadin/tests/minitutorials/broadcastingmessages/Broadcaster.java index 57ad0d97ba..78d0af6283 100644 --- a/uitest/src/com/vaadin/tests/minitutorials/broadcastingmessages/Broadcaster.java +++ b/uitest/src/com/vaadin/tests/minitutorials/broadcastingmessages/Broadcaster.java @@ -16,44 +16,25 @@ package com.vaadin.tests.minitutorials.broadcastingmessages; -import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; public class Broadcaster { - private static List<BroadcastListener> listeners = new ArrayList<BroadcastListener>(); + private static final List<BroadcastListener> listeners = new CopyOnWriteArrayList<BroadcastListener>(); - public synchronized static void register(BroadcastListener listener) { + public static void register(BroadcastListener listener) { listeners.add(listener); } - public synchronized static void unregister(BroadcastListener listener) { + public static void unregister(BroadcastListener listener) { listeners.remove(listener); } - private synchronized static List<BroadcastListener> getListeners() { - List<BroadcastListener> listenerCopy = new ArrayList<BroadcastListener>(); - listenerCopy.addAll(listeners); - return listenerCopy; - } - public static void broadcast(final String message) { - // Make a copy of the listener list while synchronized, can't be - // synchronized while firing the event or we would have to fire each - // event in a separate thread. - final List<BroadcastListener> listenerCopy = getListeners(); - - // We spawn another thread to avoid potential deadlocks with - // multiple UIs locked simultaneously - Thread eventThread = new Thread() { - @Override - public void run() { - for (BroadcastListener listener : listenerCopy) { - listener.receiveBroadcast(message); - } - } - }; - eventThread.start(); + for (BroadcastListener listener : listeners) { + listener.receiveBroadcast(message); + } } public interface BroadcastListener { diff --git a/uitest/src/com/vaadin/tests/minitutorials/broadcastingmessages/BroadcasterUI.java b/uitest/src/com/vaadin/tests/minitutorials/broadcastingmessages/BroadcasterUI.java index 06ead20db3..68b5925f48 100644 --- a/uitest/src/com/vaadin/tests/minitutorials/broadcastingmessages/BroadcasterUI.java +++ b/uitest/src/com/vaadin/tests/minitutorials/broadcastingmessages/BroadcasterUI.java @@ -1,5 +1,6 @@ package com.vaadin.tests.minitutorials.broadcastingmessages; +import com.vaadin.annotations.Push; import com.vaadin.server.VaadinRequest; import com.vaadin.tests.minitutorials.broadcastingmessages.Broadcaster.BroadcastListener; import com.vaadin.ui.Button; @@ -10,6 +11,7 @@ import com.vaadin.ui.TextArea; import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; +@Push public class BroadcasterUI extends UI implements BroadcastListener { @Override diff --git a/uitest/src/com/vaadin/tests/push/BasicPushStreaming.java b/uitest/src/com/vaadin/tests/push/BasicPushStreaming.java new file mode 100644 index 0000000000..37a8afd819 --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/BasicPushStreaming.java @@ -0,0 +1,12 @@ +package com.vaadin.tests.push; + +import com.vaadin.annotations.Push; +import com.vaadin.shared.ui.ui.Transport; + +@Push(transport = Transport.STREAMING) +public class BasicPushStreaming extends BasicPush { + @Override + protected void setup(com.vaadin.server.VaadinRequest request) { + addComponent(new PushConfigurator(this)); + } +} diff --git a/uitest/src/com/vaadin/tests/push/BasicPushWebsocket.java b/uitest/src/com/vaadin/tests/push/BasicPushWebsocket.java new file mode 100644 index 0000000000..6fc27e8974 --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/BasicPushWebsocket.java @@ -0,0 +1,8 @@ +package com.vaadin.tests.push; + +import com.vaadin.annotations.Push; +import com.vaadin.shared.ui.ui.Transport; + +@Push(transport = Transport.WEBSOCKET) +public class BasicPushWebsocket extends BasicPush { +} diff --git a/uitest/src/com/vaadin/tests/push/PushConfiguration.html b/uitest/src/com/vaadin/tests/push/PushConfiguration.html new file mode 100644 index 0000000000..c3786b1cc1 --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/PushConfiguration.html @@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="http://localhost:8888/" /> +<title>New Test</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">New Test</td></tr> +</thead><tbody> +<!--Websocket--> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.push.PushConfigurationTest?debug&restartApplication</td> + <td></td> +</tr> +<tr> + <td>assertNotText</td> + <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td> + <td>4</td> +</tr> +<tr> + <td>select</td> + <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[1]/VNativeSelect[0]/domChild[0]</td> + <td>label=WEBSOCKET</td> +</tr> +<tr> + <td>assertNotText</td> + <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td> + <td>4</td> +</tr> +<tr> + <td>select</td> + <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VNativeSelect[0]/domChild[0]</td> + <td>label=AUTOMATIC</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[5]/VLabel[0]/domChild[0]</td> + <td>*fallbackTransport: streaming*transport: websocket*</td> +</tr> +<tr> + <td>assertNotText</td> + <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td> + <td>4</td> +</tr> +<tr> + <td>waitForText</td> + <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td> + <td>4</td> +</tr> +<!--Use debug console to verify we used the correct transport type--> +<tr> + <td>assertTextPresent</td> + <td>Push connection established using websocket</td> + <td></td> +</tr> +<tr> + <td>assertTextNotPresent</td> + <td>Push connection established using streaming</td> + <td>Push connection established using streaming</td> +</tr> +<tr> + <td>select</td> + <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VNativeSelect[0]/domChild[0]</td> + <td>label=DISABLED</td> +</tr> +<!--Streaming--> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.push.PushConfigurationTest?debug&restartApplication</td> + <td></td> +</tr> +<tr> + <td>assertNotText</td> + <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td> + <td>4</td> +</tr> +<tr> + <td>select</td> + <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[1]/VNativeSelect[0]/domChild[0]</td> + <td>label=STREAMING</td> +</tr> +<tr> + <td>assertNotText</td> + <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td> + <td>4</td> +</tr> +<tr> + <td>select</td> + <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VNativeSelect[0]/domChild[0]</td> + <td>label=AUTOMATIC</td> +</tr> +<tr> + <td>assertNotText</td> + <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td> + <td>4</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[5]/VLabel[0]/domChild[0]</td> + <td>*fallbackTransport: streaming*transport: streaming*</td> +</tr> +<tr> + <td>waitForText</td> + <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td> + <td>4</td> +</tr> +<!--Use debug console to verify we used the correct transport type--> +<tr> + <td>assertTextNotPresent</td> + <td>Push connection established using websocket</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Push connection established using streaming</td> + <td></td> +</tr> +<tr> + <td>select</td> + <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VNativeSelect[0]/domChild[0]</td> + <td>label=DISABLED</td> +</tr> +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java b/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java new file mode 100644 index 0000000000..b57e9732cc --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java @@ -0,0 +1,102 @@ +package com.vaadin.tests.push; + +import java.util.Date; +import java.util.Timer; +import java.util.TimerTask; + +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.label.ContentMode; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Label; + +public class PushConfigurationTest extends AbstractTestUI { + + private ObjectProperty<Integer> counter = new ObjectProperty<Integer>(0); + + private ObjectProperty<Integer> counter2 = new ObjectProperty<Integer>(0); + + private final Timer timer = new Timer(true); + + private final TimerTask task = new TimerTask() { + + @Override + public void run() { + access(new Runnable() { + @Override + public void run() { + counter2.setValue(counter2.getValue() + 1); + } + }); + } + }; + + @Override + protected void setup(VaadinRequest request) { + addComponent(new PushConfigurator(this)); + spacer(); + + /* + * Client initiated push. + */ + Label lbl = new Label(counter); + lbl.setCaption("Client counter (click 'increment' to update):"); + addComponent(lbl); + + addComponent(new Button("Increment", new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + counter.setValue(counter.getValue() + 1); + } + })); + + spacer(); + + /* + * Server initiated push. + */ + lbl = new Label(counter2); + lbl.setCaption("Server counter (updates each 1s by server thread) :"); + addComponent(lbl); + + addComponent(new Button("Reset", new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + counter2.setValue(0); + } + })); + } + + @Override + protected String getTestDescription() { + return "This test tests the very basic operations of push. " + + "It tests that client initiated changes are " + + "recieved back to the client as well as server " + + "initiated changes are correctly updated to the client."; + } + + @Override + protected Integer getTicketNumber() { + return 11494; + } + + private void spacer() { + addComponent(new Label("<hr/>", ContentMode.HTML)); + } + + @Override + public void attach() { + super.attach(); + timer.scheduleAtFixedRate(task, new Date(), 1000); + } + + @Override + public void detach() { + super.detach(); + timer.cancel(); + } +} diff --git a/uitest/src/com/vaadin/tests/push/PushConfigurator.java b/uitest/src/com/vaadin/tests/push/PushConfigurator.java new file mode 100644 index 0000000000..6528366b59 --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/PushConfigurator.java @@ -0,0 +1,152 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +/** + * + */ +package com.vaadin.tests.push; + +import java.util.ArrayList; +import java.util.Collections; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.shared.communication.PushMode; +import com.vaadin.shared.ui.label.ContentMode; +import com.vaadin.shared.ui.ui.Transport; +import com.vaadin.ui.Alignment; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.NativeSelect; +import com.vaadin.ui.PushConfiguration; +import com.vaadin.ui.TextField; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalLayout; + +/** + * + * @since 7.1 + * @author Vaadin Ltd + */ +public class PushConfigurator extends VerticalLayout { + private NativeSelect pushMode = new NativeSelect("Push mode"); + private NativeSelect transport = new NativeSelect("Transport"); + private NativeSelect fallbackTransport = new NativeSelect("Fallback"); + private TextField parameter = new TextField("Parameter"); + private TextField value = new TextField("Value"); + private Button set = new Button("Set"); + private HorizontalLayout paramValue = new HorizontalLayout(); + private VerticalLayout vl = new VerticalLayout(); + private UI ui; + + private Label status = new Label("", ContentMode.PREFORMATTED); + + public PushConfigurator(UI ui) { + this.ui = ui; + construct(); + refreshStatus(); + } + + /** + * @since + */ + private void refreshStatus() { + PushConfiguration pc = ui.getPushConfiguration(); + String value = ""; + ArrayList<String> names = new ArrayList<String>(); + names.addAll(pc.getParameterNames()); + Collections.sort(names); + for (String param : names) { + value += param + ": " + pc.getParameter(param) + "\n"; + } + status.setValue(value); + } + + /** + * @since + */ + private void construct() { + pushMode.addItem(PushMode.DISABLED); + pushMode.addItem(PushMode.MANUAL); + pushMode.addItem(PushMode.AUTOMATIC); + + for (Transport t : Transport.values()) { + transport.addItem(t.toString()); + fallbackTransport.addItem(t.toString()); + } + transport.addItem(""); + fallbackTransport.addItem(""); + + pushMode.setImmediate(true); + transport.setImmediate(true); + fallbackTransport.setImmediate(true); + + listeners(); + + paramValue.setDefaultComponentAlignment(Alignment.BOTTOM_RIGHT); + paramValue.addComponents(parameter, value, set); + vl.addComponents(pushMode, transport, fallbackTransport, paramValue, + new Label("<hr/>", ContentMode.HTML), status); + addComponent(vl); + + } + + /** + * @since + */ + private void listeners() { + pushMode.addValueChangeListener(new ValueChangeListener() { + @Override + public void valueChange(ValueChangeEvent event) { + ui.getPushConfiguration().setPushMode( + (PushMode) pushMode.getValue()); + refreshStatus(); + } + }); + + transport.addValueChangeListener(new ValueChangeListener() { + @Override + public void valueChange(ValueChangeEvent event) { + Transport t = Transport.valueOf((String) transport.getValue()); + ui.getPushConfiguration().setTransport(t); + refreshStatus(); + } + }); + + fallbackTransport.addValueChangeListener(new ValueChangeListener() { + @Override + public void valueChange(ValueChangeEvent event) { + Transport t = Transport.valueOf((String) fallbackTransport + .getValue()); + ui.getPushConfiguration().setFallbackTransport(t); + refreshStatus(); + } + }); + + set.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + ui.getPushConfiguration().setParameter(parameter.getValue(), + value.getValue()); + refreshStatus(); + } + }); + + } +} diff --git a/uitest/src/com/vaadin/tests/push/PushTransportAnnotation.html b/uitest/src/com/vaadin/tests/push/PushTransportAnnotation.html new file mode 100644 index 0000000000..854dd458bb --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/PushTransportAnnotation.html @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="http://localhost:8888/" /> +<title>New Test</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">New Test</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.push.BasicPushStreaming?debug&restartApplication</td> + <td></td> +</tr> +<tr> + <td>waitForTextPresent</td> + <td>Push connection established using streaming</td> + <td></td> +</tr> +<tr> + <td>assertTextNotPresent</td> + <td>Push connection established using websocket</td> + <td></td> +</tr> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.push.BasicPushWebsocket?debug&restartApplication</td> + <td></td> +</tr> +<tr> + <td>assertTextNotPresent</td> + <td>Push connection established using streaming</td> + <td></td> +</tr> +<tr> + <td>waitForTextPresent</td> + <td>Push connection established using websocket</td> + <td></td> +</tr> +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/push/TogglePush.java b/uitest/src/com/vaadin/tests/push/TogglePush.java index 37687260dd..c0bdc54ee0 100644 --- a/uitest/src/com/vaadin/tests/push/TogglePush.java +++ b/uitest/src/com/vaadin/tests/push/TogglePush.java @@ -22,19 +22,22 @@ public class TogglePush extends AbstractTestUI { updateCounter(); addComponent(counterLabel); - setPushMode("disabled".equals(request.getParameter("push")) ? PushMode.DISABLED - : PushMode.AUTOMATIC); + getPushConfiguration() + .setPushMode( + "disabled".equals(request.getParameter("push")) ? PushMode.DISABLED + : PushMode.AUTOMATIC); CheckBox pushSetting = new CheckBox("Push enabled"); - pushSetting.setValue(Boolean.valueOf(getPushMode().isEnabled())); + pushSetting.setValue(Boolean.valueOf(getPushConfiguration() + .getPushMode().isEnabled())); pushSetting.setImmediate(true); pushSetting.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { if (event.getProperty().getValue() == Boolean.TRUE) { - setPushMode(PushMode.AUTOMATIC); + getPushConfiguration().setPushMode(PushMode.AUTOMATIC); } else { - setPushMode(PushMode.DISABLED); + getPushConfiguration().setPushMode(PushMode.DISABLED); } } }); diff --git a/uitest/src/com/vaadin/tests/themes/CSSInjectTest.html b/uitest/src/com/vaadin/tests/themes/CSSInjectTest.html index 05a0f256c2..0c70d6f711 100644 --- a/uitest/src/com/vaadin/tests/themes/CSSInjectTest.html +++ b/uitest/src/com/vaadin/tests/themes/CSSInjectTest.html @@ -51,7 +51,16 @@ <td></td> <td>world-red</td> </tr> - +<tr> + <td>click</td> + <td>vaadin=runcomvaadinteststhemesCSSInjectTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[4]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>world-still-red</td> +</tr> </tbody></table> </body> </html> diff --git a/uitest/src/com/vaadin/tests/themes/CSSInjectTest.java b/uitest/src/com/vaadin/tests/themes/CSSInjectTest.java index f4448bf326..738d8fc681 100644 --- a/uitest/src/com/vaadin/tests/themes/CSSInjectTest.java +++ b/uitest/src/com/vaadin/tests/themes/CSSInjectTest.java @@ -22,14 +22,16 @@ public class CSSInjectTest extends TestBase { final Styles stylesheet = Page.getCurrent().getStyles(); // Inject some resources initially - stylesheet.add(new StreamResource(new StreamResource.StreamSource() { + final StreamResource initialResource = new StreamResource( + new StreamResource.StreamSource() { - @Override - public InputStream getStream() { - return new ByteArrayInputStream( - ".hello, .world { color:silver; }".getBytes()); - } - }, "mystyles-" + System.currentTimeMillis() + ".css")); + @Override + public InputStream getStream() { + return new ByteArrayInputStream( + ".hello, .world { color:silver; }".getBytes()); + } + }, "mystyles-" + System.currentTimeMillis() + ".css"); + stylesheet.add(initialResource); Label hello = new Label( "<span class='hello'>Hello</span> <span class='world'>world</span>", @@ -72,6 +74,14 @@ public class CSSInjectTest extends TestBase { } }); addComponent(injectRandom); + + addComponent(new Button("Inject initial again!", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + stylesheet.add(initialResource); + } + })); } @Override diff --git a/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml b/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml index 1b47a86113..fd52e5cd0e 100644 --- a/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml +++ b/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml @@ -1,15 +1,16 @@ <module> - <!-- WS Compiler: manually edited --> + <!-- WS Compiler: manually edited --> + + <!-- Inherit the DefaultWidgetSet --> + <inherits name="com.vaadin.DefaultWidgetSet" /> - <!-- Inherit the DefaultWidgetSet --> - <inherits name="com.vaadin.DefaultWidgetSet" /> - <replace-with class="com.vaadin.tests.widgetset.client.CustomUIConnector"> <when-type-is class="com.vaadin.client.ui.ui.UIConnector" /> </replace-with> - - <replace-with class="com.vaadin.tests.widgetset.client.TestingPushConnection"> + + <replace-with + class="com.vaadin.tests.widgetset.client.TestingPushConnection"> <when-type-is class="com.vaadin.client.communication.PushConnection" /> </replace-with> - + </module> diff --git a/uitest/src/com/vaadin/tests/widgetset/client/TestingPushConnection.java b/uitest/src/com/vaadin/tests/widgetset/client/TestingPushConnection.java index 8d00598907..4dae8892e7 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/TestingPushConnection.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/TestingPushConnection.java @@ -2,15 +2,19 @@ package com.vaadin.tests.widgetset.client; import com.google.gwt.user.client.Window; import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.ApplicationConnection.CommunicationErrorHandler; import com.vaadin.client.communication.AtmospherePushConnection; +import com.vaadin.shared.ui.ui.UIState.PushConfigurationState; public class TestingPushConnection extends AtmospherePushConnection { private String transport; @Override - public void init(ApplicationConnection connection) { - super.init(connection); + public void init(ApplicationConnection connection, + PushConfigurationState pushConfiguration, + CommunicationErrorHandler errorHandler) { + super.init(connection, pushConfiguration, errorHandler); transport = Window.Location.getParameter("transport"); } diff --git a/uitest/test.xml b/uitest/test.xml index 8228bd9d70..44dac13d90 100644 --- a/uitest/test.xml +++ b/uitest/test.xml @@ -1,189 +1,227 @@ <?xml version="1.0"?> -<project xmlns:antcontrib="antlib:net.sf.antcontrib" xmlns:ivy="antlib:org.apache.ivy.ant" name="Run Vaadin Testbench Tests" basedir="." default="run-and-clean-up"> - - <include file="../common.xml" /> - <dirname property="test.xml.dir" file="${ant.file.Run Vaadin Testbench Tests}" /> - - <!-- ================================================================== --> - <!-- Configuration --> - <!-- ================================================================== --> - <!-- Browsers to use for testing --> - <property name="browsers-windows" value="winxp-ie8,win7-ie9,win7-ie10,winxp-firefox17-esr,winxp-safari5,winxp-googlechrome21,winxp-opera12" /> - <property name="browsers-linux" value="linux-firefox3,linux-opera10,linux-googlechrome8" /> - <property name="browsers-mac" value="osx-firefox3,osx-opera10,osx-googlechrome8,osx-safari4,osx-safari5" /> - - <property name="browsers" value="${browsers-windows}" /> - - <!-- Number of times to retry a test if it fails --> - <property name="retries" value="2" /> - - <!-- Screen shot base directory --> - <fail unless="com.vaadin.testbench.screenshot.directory" message="The 'com.vaadin.testbench.screenshot.directory' property must be defined." /> - - <!-- Screen shot resolution --> - <property name="com.vaadin.testbench.screenshot.resolution" value="1500x850" /> - - <!-- Host running Testbench Hub --> - <property name="com.vaadin.testbench.tester.host" value="testbench-hub.intra.itmill.com" /> - - <property name="com.vaadin.testbench.screenshot.block.error" value="0.025" /> - <property name="com.vaadin.testbench.debug" value="false" /> - - - <target name="initialize"> - <!-- classpath must include test bench jar and its dependencies --> - <path id="classpath"> - <fileset dir="${com.vaadin.testbench.lib.dir}" includes="**/*.jar" /> - </path> - </target> - - <!-- fileset containing all TestBench tests to run --> - <fileset dir="${test.xml.dir}" id="html-test-files"> - <include name="src/**/*.html" /> - <exclude name="integration-testscripts/**/*.html" /> - </fileset> - - <!-- This target converts HTML tests files to java junit tests. One test file for each browser is created. --> - <target name="create-tests" depends="initialize, remove-temp-testclasses"> - <!-- Temporary output directory, created and removed by this script --> - <fail unless="test-output-dir" message="The 'test-output-dir' property must be defined." /> - <property name="class-dir" value="${test-output-dir}/classes" /> - - <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> - - <java classname="com.vaadin.testbench.util.TestConverter" classpathref="classpath" fork="true"> - <sysproperty key="com.vaadin.testbench.test.retries" value="${retries}" /> - <jvmarg value="-Duser.language=en" /> - <jvmarg value="-Duser.country=US" /> - <arg value="${test-output-dir}" /> - <arg value="${browsers}" /> - <arg line="${testfiles}" /> - </java> - </target> - - - <!-- This target complies the generated java junit tests. --> - <target name="compile-tests" depends="create-tests"> - <mkdir dir="${class-dir}" /> - <javac includeantruntime="false" srcdir="${test-output-dir}" destdir="${class-dir}" debug="on" fork="yes" failonerror="false" encoding="UTF8"> - <classpath> - <path refid="classpath" /> - </classpath> - </javac> - </target> - - <!-- ================================================================== --> - <!-- Running Tests --> - <!-- ================================================================== --> - - <target name="check-parameters"> - <fail unless="com.vaadin.testbench.lib.dir" message="The 'com.vaadin.testbench.lib.dir' property must be defined." /> - <fail unless="com.vaadin.testbench.tester.host" message="The 'com.vaadin.testbench.tester.host' property must be defined." /> - <fail unless="com.vaadin.testbench.deployment.url" message="The 'com.vaadin.testbench.deployment.url' property must be defined." /> - </target> - - <target name="run-tests" depends="compile-tests"> - <fileset dir="${test-output-dir}" id="tests-fileset"> - <include name="**/**.java" /> - </fileset> - - <antcontrib:for threadCount="30" parallel="true" keepgoing="true" param="target"> - <path> - <fileset refid="tests-fileset" /> - </path> - <sequential> - <antcall target="execute-tests"> - <param name="target" value="@{target}" /> - <reference refid="classpath" /> - </antcall> - </sequential> - </antcontrib:for> - </target> - - <!-- This target runs the generated and compiled junit tests --> - <target name="execute-tests"> - <junit fork="yes" printsummary="withOutAndErr" maxmemory="96m"> - <classpath> - <path refid="classpath" /> - <pathelement path="${class-dir}" /> - </classpath> - - <formatter usefile="false" type="plain" /> - - <jvmarg value="-Dcom.vaadin.testbench.tester.host=${com.vaadin.testbench.tester.host}" /> - <jvmarg value="-Dcom.vaadin.testbench.deployment.url=${com.vaadin.testbench.deployment.url}" /> - <!-- Define where the reference screenshots and diff files are saved --> - <jvmarg value="-Dcom.vaadin.testbench.screenshot.directory=${com.vaadin.testbench.screenshot.directory}" /> - <!-- Resolution for screenshots --> - <jvmarg value="-Dcom.vaadin.testbench.screenshot.resolution=${com.vaadin.testbench.screenshot.resolution}" /> - <jvmarg value="-Dcom.vaadin.testbench.debug=${com.vaadin.testbench.debug}" /> - <jvmarg value="-Dcom.vaadin.testbench.screenshot.block.error=${com.vaadin.testbench.screenshot.block.error}" /> - - - <jvmarg value="-Djava.awt.headless=true" /> - - <!-- true/false system arguments --> - <jvmarg value="-Dcom.vaadin.testbench.screenshot.softfail=${com.vaadin.testbench.screenshot.softfail}" /> - <jvmarg value="-Dcom.vaadin.testbench.screenshot.reference.debug=${com.vaadin.testbench.screenshot.reference.debug}" /> - <jvmarg value="-Dcom.vaadin.testbench.screenshot.cursor=${com.vaadin.testbench.screenshot.cursor}" /> - - <batchtest> - <filelist dir="${test-output-dir}" files="${target}" /> - </batchtest> - </junit> - - </target> - - <!-- Remove temporary source and compiled java files --> - <target name="remove-temp-testclasses"> - <delete failonerror="false"> - <fileset dir="${test-output-dir}"> - <include name="**/**.java" /> - <include name="**/**.class" /> - </fileset> - </delete> - </target> - - <!-- Remove old error screenshots --> - <target name="remove-error-screens"> - <mkdir dir="${com.vaadin.testbench.screenshot.directory}/errors" /> - <delete> - <fileset dir="${com.vaadin.testbench.screenshot.directory}/errors"> - <include name="**/**.*" /> - </fileset> - </delete> - </target> - - <!-- ================================================================== --> - <!-- Main Targets --> - <!-- ================================================================== --> - - <!-- The default target. --> - <target name="run-and-clean-up" depends="check-parameters,remove-error-screens,run-tests" /> - - - <!-- Starts the server and runs all TestBench tests --> - <target name="test-package"> - <fail unless="war.file" message="No 'war.file' parameter given." /> - <property name="test-output-dir" location="${test.xml.dir}/result/testbench-junit-classes" /> - <property name="retries" value="2" /> - - <!-- Parameters for the test.xml script. --> - <fail unless="com.vaadin.testbench.tester.host" message="The 'com.vaadin.testbench.tester.host' property must be defined." /> - <fail unless="com.vaadin.testbench.deployment.url" message="The 'com.vaadin.testbench.deployment.url' property must be defined." /> - <fail unless="com.vaadin.testbench.lib.dir" message="The 'com.vaadin.testbench.lib.dir' property must be defined." /> - <property name="com.vaadin.testbench.screenshot.block.error" value="0.025" /> - <property name="com.vaadin.testbench.debug" value="false" /> - - <parallel> - <daemons> - <ant antfile="${test.xml.dir}/vaadin-server.xml" inheritall="true" inheritrefs="true" target="deploy-and-start" /> - </daemons> - <sequential> - <ant antfile="${test.xml.dir}/vaadin-server.xml" target="wait-for-startup" /> - <antcall inheritall="true" inheritrefs="true" target="run-and-clean-up" /> - <echo message="All TestBench tests have been run" /> - </sequential> - </parallel> - </target> +<project xmlns:antcontrib="antlib:net.sf.antcontrib" xmlns:ivy="antlib:org.apache.ivy.ant" + name="Run Vaadin Testbench Tests" basedir="." default="run-and-clean-up"> + + <include file="../common.xml" /> + <dirname property="test.xml.dir" file="${ant.file.Run Vaadin Testbench Tests}" /> + + <!-- ================================================================== --> + <!-- Configuration --> + <!-- ================================================================== --> + <!-- Browsers to use for testing --> + <property name="browsers-windows" + value="winxp-ie8,win7-ie9,win7-ie10,winxp-firefox17-esr,winxp-safari5,winxp-googlechrome21,winxp-opera12" /> + <property name="browsers-linux" + value="linux-firefox3,linux-opera10,linux-googlechrome8" /> + <property name="browsers-mac" + value="osx-firefox3,osx-opera10,osx-googlechrome8,osx-safari4,osx-safari5" /> + + <property name="browsers" value="${browsers-windows}" /> + + <!-- Number of times to retry a test if it fails --> + <property name="retries" value="2" /> + + <!-- Screen shot base directory --> + <fail unless="com.vaadin.testbench.screenshot.directory" + message="The 'com.vaadin.testbench.screenshot.directory' property must be defined." /> + + <!-- Screen shot resolution --> + <property name="com.vaadin.testbench.screenshot.resolution" + value="1500x850" /> + + <!-- Host running Testbench Hub --> + <property name="com.vaadin.testbench.tester.host" value="testbench-hub.intra.itmill.com" /> + + <property name="com.vaadin.testbench.screenshot.block.error" + value="0.025" /> + <property name="com.vaadin.testbench.debug" value="false" /> + + + <target name="initialize"> + <!-- classpath must include test bench jar and its dependencies --> + <path id="classpath"> + <fileset dir="${com.vaadin.testbench.lib.dir}" + includes="**/*.jar" /> + </path> + </target> + + <!-- fileset containing all TestBench tests to run --> + <fileset dir="${test.xml.dir}" id="html-test-files"> + <include name="src/**/*.html" /> + <exclude name="integration-testscripts/**/*.html" /> + </fileset> + + <!-- This target converts HTML tests files to java junit tests. One test + file for each browser is created. --> + <target name="create-tests" depends="initialize, remove-temp-testclasses"> + <!-- Temporary output directory, created and removed by this script --> + <fail unless="test-output-dir" + message="The 'test-output-dir' property must be defined." /> + <property name="class-dir" value="${test-output-dir}/classes" /> + + <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> + + <java classname="com.vaadin.testbench.util.TestConverter" + classpathref="classpath" fork="true"> + <sysproperty key="com.vaadin.testbench.test.retries" + value="${retries}" /> + <jvmarg value="-Duser.language=en" /> + <jvmarg value="-Duser.country=US" /> + <arg value="${test-output-dir}" /> + <arg value="${browsers}" /> + <arg line="${testfiles}" /> + </java> + </target> + + + <!-- This target complies the generated java junit tests. --> + <target name="compile-tests" depends="create-tests"> + <mkdir dir="${class-dir}" /> + <javac includeantruntime="false" srcdir="${test-output-dir}" + destdir="${class-dir}" debug="on" fork="yes" failonerror="false" + encoding="UTF8"> + <classpath> + <path refid="classpath" /> + </classpath> + </javac> + </target> + + <!-- ================================================================== --> + <!-- Running Tests --> + <!-- ================================================================== --> + + <target name="check-parameters"> + <fail unless="com.vaadin.testbench.lib.dir" + message="The 'com.vaadin.testbench.lib.dir' property must be defined." /> + <fail unless="com.vaadin.testbench.tester.host" + message="The 'com.vaadin.testbench.tester.host' property must be defined." /> + <fail unless="com.vaadin.testbench.deployment.url" + message="The 'com.vaadin.testbench.deployment.url' property must be defined." /> + </target> + + <target name="run-tests" depends="compile-tests"> + <fileset dir="${test-output-dir}" id="tests-fileset"> + <include name="**/**.java" /> + </fileset> + + <antcontrib:for threadCount="30" parallel="true" + keepgoing="true" param="target"> + <path> + <fileset refid="tests-fileset" /> + </path> + <sequential> + <antcall target="execute-tests"> + <param name="target" value="@{target}" /> + <reference refid="classpath" /> + </antcall> + </sequential> + </antcontrib:for> + </target> + + <!-- This target runs the generated and compiled junit tests --> + <target name="execute-tests"> + <junit fork="yes" printsummary="withOutAndErr" maxmemory="96m"> + <classpath> + <path refid="classpath" /> + <pathelement path="${class-dir}" /> + </classpath> + + <formatter usefile="false" type="plain" /> + + <jvmarg + value="-Dcom.vaadin.testbench.tester.host=${com.vaadin.testbench.tester.host}" /> + <jvmarg + value="-Dcom.vaadin.testbench.deployment.url=${com.vaadin.testbench.deployment.url}" /> + <!-- Define where the reference screenshots and diff files are + saved --> + <jvmarg + value="-Dcom.vaadin.testbench.screenshot.directory=${com.vaadin.testbench.screenshot.directory}" /> + <!-- Resolution for screenshots --> + <jvmarg + value="-Dcom.vaadin.testbench.screenshot.resolution=${com.vaadin.testbench.screenshot.resolution}" /> + <jvmarg + value="-Dcom.vaadin.testbench.debug=${com.vaadin.testbench.debug}" /> + <jvmarg + value="-Dcom.vaadin.testbench.screenshot.block.error=${com.vaadin.testbench.screenshot.block.error}" /> + + + <jvmarg value="-Djava.awt.headless=true" /> + + <!-- true/false system arguments --> + <jvmarg + value="-Dcom.vaadin.testbench.screenshot.softfail=${com.vaadin.testbench.screenshot.softfail}" /> + <jvmarg + value="-Dcom.vaadin.testbench.screenshot.reference.debug=${com.vaadin.testbench.screenshot.reference.debug}" /> + <jvmarg + value="-Dcom.vaadin.testbench.screenshot.cursor=${com.vaadin.testbench.screenshot.cursor}" /> + + <batchtest> + <filelist dir="${test-output-dir}" files="${target}" /> + </batchtest> + </junit> + + </target> + + <!-- Remove temporary source and compiled java files --> + <target name="remove-temp-testclasses"> + <delete failonerror="false"> + <fileset dir="${test-output-dir}"> + <include name="**/**.java" /> + <include name="**/**.class" /> + </fileset> + </delete> + </target> + + <!-- Remove old error screenshots --> + <target name="remove-error-screens"> + <mkdir dir="${com.vaadin.testbench.screenshot.directory}/errors" /> + <delete> + <fileset + dir="${com.vaadin.testbench.screenshot.directory}/errors"> + <include name="**/**.*" /> + </fileset> + </delete> + </target> + + <!-- ================================================================== --> + <!-- Main Targets --> + <!-- ================================================================== --> + + <!-- The default target. --> + <target name="run-and-clean-up" + depends="check-parameters,remove-error-screens,run-tests" /> + + + <!-- Starts the server and runs all TestBench tests --> + <target name="test-package"> + <fail unless="war.file" message="No 'war.file' parameter given." /> + <property name="test-output-dir" + location="${test.xml.dir}/result/testbench-junit-classes" /> + <property name="retries" value="2" /> + + <!-- Parameters for the test.xml script. --> + <fail unless="com.vaadin.testbench.tester.host" + message="The 'com.vaadin.testbench.tester.host' property must be defined." /> + <fail unless="com.vaadin.testbench.deployment.url" + message="The 'com.vaadin.testbench.deployment.url' property must be defined." /> + <fail unless="com.vaadin.testbench.lib.dir" + message="The 'com.vaadin.testbench.lib.dir' property must be defined." /> + <property name="com.vaadin.testbench.screenshot.block.error" + value="0.025" /> + <property name="com.vaadin.testbench.debug" value="false" /> + + <parallel> + <daemons> + <ant antfile="${test.xml.dir}/vaadin-server.xml" + inheritall="true" inheritrefs="true" target="deploy-and-start" /> + </daemons> + <sequential> + <ant antfile="${test.xml.dir}/vaadin-server.xml" + target="wait-for-startup" /> + <antcall inheritall="true" inheritrefs="true" + target="run-and-clean-up" /> + <echo message="All TestBench tests have been run" /> + </sequential> + </parallel> + </target> </project> diff --git a/uitest/vaadin-server.xml b/uitest/vaadin-server.xml index 5741d78525..4b32cebe26 100644 --- a/uitest/vaadin-server.xml +++ b/uitest/vaadin-server.xml @@ -1,34 +1,38 @@ <?xml version="1.0"?> -<project xmlns:antcontrib="antlib:net.sf.antcontrib" xmlns:ivy="antlib:org.apache.ivy.ant" name="vaadin-server" default="deploy-and-start" basedir="."> - <include file="../common.xml" /> - <dirname property="dir" file="${ant.file.vaadin-server}" /> +<project xmlns:antcontrib="antlib:net.sf.antcontrib" xmlns:ivy="antlib:org.apache.ivy.ant" + name="vaadin-server" default="deploy-and-start" basedir="."> + <include file="../common.xml" /> + <dirname property="dir" file="${ant.file.vaadin-server}" /> - <target name="deploy-and-start"> - <fail unless="war.file" message="No war file given in 'war.file'" /> + <target name="deploy-and-start"> + <fail unless="war.file" message="No war file given in 'war.file'" /> - <ivy:resolve file="${dir}/ivy.xml" /> - <ivy:cachepath pathid="classpath.jetty" conf="jetty-run" /> - <java classname="org.mortbay.jetty.runner.Runner" fork="yes" output="${vaadin.basedir}/result/jetty.java.out" resultproperty="resultCode"> - <arg value="--port" /> - <arg value="8888" /> - <arg value="--out" /> - <arg value="${vaadin.basedir}/result/jetty.out" /> - <arg value="--log" /> - <arg value="${vaadin.basedir}/result/jetty.log" /> - <arg value="${war.file}" /> - <classpath refid="classpath.jetty" /> - <jvmarg value="-ea" /> - </java> - <echo message="Jetty process ended with result code ${resultCode}" /> + <ivy:resolve file="${dir}/ivy.xml" /> + <ivy:cachepath pathid="classpath.jetty" conf="jetty-run" /> + <java classname="org.mortbay.jetty.runner.Runner" fork="yes" + output="${vaadin.basedir}/result/jetty.java.out" + resultproperty="resultCode"> + <arg value="--port" /> + <arg value="8888" /> + <arg value="--out" /> + <arg value="${vaadin.basedir}/result/jetty.out" /> + <arg value="--log" /> + <arg value="${vaadin.basedir}/result/jetty.log" /> + <arg value="${war.file}" /> + <classpath refid="classpath.jetty" /> + <jvmarg value="-ea" /> + </java> + <echo message="Jetty process ended with result code ${resultCode}" /> - </target> + </target> - <target name="wait-for-startup"> - <echo>Waiting for Servlet Container to start up.</echo> - <waitfor maxwait="60" maxwaitunit="second" checkevery="5" checkeveryunit="second" timeoutproperty="server.start.failed"> - <http url="http://localhost:8888" /> - </waitfor> - <fail if="server.start.failed" message="Server startup failed" /> - </target> + <target name="wait-for-startup"> + <echo>Waiting for Servlet Container to start up.</echo> + <waitfor maxwait="60" maxwaitunit="second" checkevery="5" + checkeveryunit="second" timeoutproperty="server.start.failed"> + <http url="http://localhost:8888" /> + </waitfor> + <fail if="server.start.failed" message="Server startup failed" /> + </target> </project> |