SQL工作台:引入cometd技术,用于支持SQL执行反馈

This commit is contained in:
datagear 2019-03-13 22:02:16 +08:00
parent 86cd42ad01
commit 6d23f52be9
17 changed files with 4339 additions and 14 deletions

View File

@ -147,6 +147,11 @@
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
<dependency>
<groupId>org.cometd.java</groupId>
<artifactId>cometd-java-server</artifactId>
<version>2.9.1</version>
</dependency>
</dependencies>
<build>

View File

@ -4,18 +4,25 @@
package org.datagear.web.controller;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.cometd.bayeux.server.BayeuxServer;
import org.cometd.bayeux.server.ServerChannel;
import org.cometd.bayeux.server.ServerSession;
import org.datagear.connection.ConnectionSource;
import org.datagear.management.domain.Schema;
import org.datagear.management.service.SchemaService;
import org.datagear.web.convert.ClassDataConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* SQL工作台控制器
@ -27,6 +34,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
@RequestMapping("/sqlpad")
public class SqlpadController extends AbstractSchemaConnController
{
@Autowired
private BayeuxServer bayeuxServer;
public SqlpadController()
{
super();
@ -38,6 +48,16 @@ public class SqlpadController extends AbstractSchemaConnController
super(messageSource, classDataConverter, schemaService, connectionSource);
}
public BayeuxServer getBayeuxServer()
{
return bayeuxServer;
}
public void setBayeuxServer(BayeuxServer bayeuxServer)
{
this.bayeuxServer = bayeuxServer;
}
@RequestMapping("/{schemaId}")
public String index(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model springModel, @PathVariable("schemaId") String schemaId) throws Throwable
@ -53,4 +73,21 @@ public class SqlpadController extends AbstractSchemaConnController
return "/sqlpad/sqlpad";
}
@RequestMapping("/message")
@ResponseBody
public String message(HttpServletRequest request, HttpServletResponse response) throws Throwable
{
String channelName = "/sqlpad";
this.bayeuxServer.createIfAbsent(channelName);
ServerChannel channel = this.bayeuxServer.getChannel(channelName);
Set<ServerSession> sessions = channel.getSubscribers();
for (ServerSession serverSession : sessions)
channel.publish(serverSession, "hello");
return "ok";
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2018 datagear.org. All Rights Reserved.
*/
package org.datagear.web.util;
import java.util.List;
import java.util.Map;
import org.cometd.bayeux.server.BayeuxServer;
import org.cometd.bayeux.server.BayeuxServer.Extension;
import org.cometd.server.BayeuxServerImpl;
/**
* {@linkplain BayeuxServer}工厂类
*
* @author datagear@163.com
*
*/
public class BayeuxServerFactory
{
private Map<String, Object> options;
private List<Extension> extensions;
public BayeuxServerFactory()
{
super();
}
public Map<String, Object> getOptions()
{
return options;
}
public void setOptions(Map<String, Object> options)
{
this.options = options;
}
public List<Extension> getExtensions()
{
return extensions;
}
public void setExtensions(List<Extension> extensions)
{
this.extensions = extensions;
}
public BayeuxServer getBayeuxServer()
{
BayeuxServerImpl bayeuxServerImpl = new BayeuxServerImpl();
if (this.options != null)
bayeuxServerImpl.setOptions(this.options);
if (this.extensions != null)
{
for (Extension extension : this.extensions)
bayeuxServerImpl.addExtension(extension);
}
return bayeuxServerImpl;
}
}

View File

@ -331,6 +331,32 @@
<bean id="changelogResolver" class="org.datagear.web.util.ChangelogResolver" />
<!-- cometd配置开始 -->
<bean id="bayeuxServerFactory" class="org.datagear.web.util.BayeuxServerFactory">
<property name="options">
<map>
<entry key="logLevel" value="3" />
<entry key="timeout" value="15000" />
</map>
</property>
<property name="extensions">
<list>
<bean class="org.cometd.server.ext.AcknowledgedMessagesExtension" />
</list>
</property>
</bean>
<bean id="bayeuxServer" factory-bean="bayeuxServerFactory" factory-method="getBayeuxServer" init-method="start" destroy-method="stop" />
<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
<map>
<entry key="org.cometd.bayeux">
<ref local="bayeuxServer" />
</entry>
</map>
</property>
</bean>
<!-- cometd配置结束 -->
<!-- 定时任务开始 -->
<!-- 删除过期的BLOB文件 -->

View File

@ -31,6 +31,12 @@ var contextPath="${contextPath}";
<script src="${contextPath}/static/script/textarea-helper-0.3.1/textarea-helper.js" type="text/javascript"></script>
<script src="${contextPath}/static/script/ace-21.02.19/ace.js" type="text/javascript"></script>
<script src="${contextPath}/static/script/ace-21.02.19/mode-sql.js" type="text/javascript"></script>
<script src="${contextPath}/static/script/cometd-2.9.1/cometd.js" type="text/javascript"></script>
<script src="${contextPath}/static/script/cometd-2.9.1/AckExtension.js" type="text/javascript"></script>
<script src="${contextPath}/static/script/cometd-2.9.1/ReloadExtension.js" type="text/javascript"></script>
<script src="${contextPath}/static/script/cometd-2.9.1/jquery.cometd.js" type="text/javascript"></script>
<script src="${contextPath}/static/script/cometd-2.9.1/jquery.cometd-ack.js" type="text/javascript"></script>
<script src="${contextPath}/static/script/cometd-2.9.1/jquery.cometd-reload.js" type="text/javascript"></script>
<script src="${contextPath}/static/script/datagear-pagination.js" type="text/javascript"></script>
<script src="${contextPath}/static/script/datagear-model.js" type="text/javascript"></script>
<script src="${contextPath}/static/script/datagear-modelcache.js" type="text/javascript"></script>

View File

@ -98,6 +98,19 @@ Schema schema 数据库不允许为null
editor.setValue("");
editor.focus();
});
var cometd = $.cometd;
if(!$.isCometdInit)
{
$.isCometdInit = true;
cometd.init("${contextPath}/cometd");
}
cometd.subscribe("/sqlpad", function(message)
{
$("<p />").html(message).appendTo(po.element(".content-result"));
});
})
(${pageId});
</script>

View File

@ -35,6 +35,7 @@
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
@ -49,22 +50,9 @@
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<servlet-name>dispatcherServlet</servlet-name>
</filter-mapping>
<!--
<filter>
<filter-name>userFilter</filter-name>
<filter-class>org.datagear.web.filter.UserFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>userFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
@ -98,6 +86,16 @@
<url-pattern>/notification/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>cometd</servlet-name>
<servlet-class>org.cometd.server.CometdServlet</servlet-class>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>cometd</servlet-name>
<url-pattern>/cometd/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>

View File

@ -0,0 +1,112 @@
/*
* Copyright (c) 2010 the original author or authors.
*
* 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.
*/
(function()
{
function bind(org_cometd)
{
/**
* This client-side extension enables the client to acknowledge to the server
* the messages that the client has received.
* For the acknowledgement to work, the server must be configured with the
* correspondent server-side ack extension. If both client and server support
* the ack extension, then the ack functionality will take place automatically.
* By enabling this extension, all messages arriving from the server will arrive
* via the long poll, so the comet communication will be slightly chattier.
* The fact that all messages will return via long poll means also that the
* messages will arrive with total order, which is not guaranteed if messages
* can arrive via both long poll and normal response.
* Messages are not acknowledged one by one, but instead a group of messages is
* acknowledged when long poll returns.
*/
return org_cometd.AckExtension = function()
{
var _cometd;
var _serverSupportsAcks = false;
var _ackId = -1;
function _debug(text, args)
{
_cometd._debug(text, args);
}
this.registered = function(name, cometd)
{
_cometd = cometd;
_debug('AckExtension: executing registration callback');
};
this.unregistered = function()
{
_debug('AckExtension: executing unregistration callback');
_cometd = null;
};
this.incoming = function(message)
{
var channel = message.channel;
if (channel == '/meta/handshake')
{
_serverSupportsAcks = message.ext && message.ext.ack;
_debug('AckExtension: server supports acks', _serverSupportsAcks);
}
else if (channel == '/meta/connect' && message.successful && _serverSupportsAcks)
{
var ext = message.ext;
if (ext && typeof ext.ack === 'number')
{
_ackId = ext.ack;
_debug('AckExtension: server sent ack id', _ackId);
}
}
return message;
};
this.outgoing = function(message)
{
var channel = message.channel;
if (channel == '/meta/handshake')
{
if (!message.ext)
{
message.ext = {};
}
message.ext.ack = _cometd && _cometd.ackEnabled !== false;
_ackId = -1;
}
else if (channel == '/meta/connect' && _serverSupportsAcks)
{
if (!message.ext)
{
message.ext = {};
}
message.ext.ack = _ackId;
_debug('AckExtension: client sending ack id', _ackId);
}
return message;
};
};
}
if (typeof define === 'function' && define.amd)
{
define(['org/cometd'], bind);
}
else
{
bind(org.cometd);
}
})();

View File

@ -0,0 +1,254 @@
/*
* Copyright (c) 2010 the original author or authors.
*
* 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.
*/
(function()
{
function bind(org_cometd)
{
if (!org_cometd.COOKIE)
{
org_cometd.COOKIE = {};
org_cometd.COOKIE.set = function(name, value, options)
{
throw 'Abstract';
};
org_cometd.COOKIE.get = function(name)
{
throw 'Abstract';
};
}
/**
* The reload extension allows a page to be loaded (or reloaded)
* without having to re-handshake in the new (or reloaded) page,
* therefore resuming the existing cometd connection.
*
* When the reload() method is called, the state of the cometd
* connection and of the cometd subscriptions is stored in a cookie
* with a short max-age.
* The reload() method must therefore be called by page unload
* handlers, often provided by JavaScript toolkits.
*
* When the page is (re)loaded, this extension checks the cookie
* and restores the cometd connection and the cometd subscriptions.
*/
return org_cometd.ReloadExtension = function(configuration)
{
var _cometd;
var _debug;
var _state = null;
var _cookieName = 'org.cometd.reload';
var _cookiePath = '/';
var _cookieMaxAge = 5;
var _batch = false;
function _reload(config)
{
if (_state && _state.handshakeResponse !== null)
{
_configure(config);
_state.cookiePath = _cookiePath;
var cookie = org_cometd.JSON.toJSON(_state);
_debug('Reload extension saving cookie value', cookie);
org_cometd.COOKIE.set(_cookieName, cookie, {
'max-age': _cookieMaxAge,
path: _cookiePath,
expires: new Date(new Date().getTime() + _cookieMaxAge * 1000)
});
}
}
function _similarState(oldState)
{
// We want to check here that the CometD object
// did not change much between reloads.
// We just check the URL for now, but in future
// further checks may involve the transport type
// and other configuration parameters.
return _state.url == oldState.url;
}
function _configure(config)
{
if (config)
{
if (typeof config.cookieMaxAge === 'number')
{
_cookieMaxAge = config.cookieMaxAge;
}
if (typeof config.cookieName === 'string')
{
_cookieName = config.cookieName;
}
if (typeof config.cookiePath === 'string')
{
_cookiePath = config.cookiePath;
}
}
}
this.configure = _configure;
this.registered = function(name, cometd)
{
_cometd = cometd;
_cometd.reload = _reload;
_debug = _cometd._debug;
};
this.unregistered = function()
{
delete _cometd.reload;
_cometd = null;
};
this.outgoing = function(message)
{
switch (message.channel)
{
case '/meta/handshake':
{
_state = {};
_state.url = _cometd.getURL();
var cookie = org_cometd.COOKIE.get(_cookieName);
_debug('Reload extension found cookie value', cookie);
// Is there a saved handshake response from a prior load ?
if (cookie)
{
try
{
var oldState = org_cometd.JSON.fromJSON(cookie);
// Remove the cookie, not needed anymore
org_cometd.COOKIE.set(_cookieName, '', {
'max-age': -1,
path: oldState.cookiePath,
expires: -1
});
if (oldState.handshakeResponse && _similarState(oldState))
{
_debug('Reload extension restoring state', oldState);
setTimeout(function ()
{
_debug('Reload extension replaying handshake response', oldState.handshakeResponse);
_state.handshakeResponse = oldState.handshakeResponse;
_state.transportType = oldState.transportType;
_state.reloading = true;
var response = _cometd._mixin(true, {}, _state.handshakeResponse, {ext: {reload: true}});
response.supportedConnectionTypes = [_state.transportType];
_cometd.receive(response);
_debug('Reload extension replayed handshake response', response);
}, 0);
// delay any sends until first connect is complete.
if (!_batch)
{
_batch = true;
_cometd.startBatch();
}
// This handshake is aborted, as we will replay the prior handshake response
return null;
}
else
{
_debug('Reload extension could not restore state', oldState);
}
}
catch (x)
{
_debug('Reload extension error while trying to restore cookie', x);
}
}
break;
}
case '/meta/connect':
{
if (!_state.transportType)
{
_state.transportType = message.connectionType;
_debug('Reload extension tracked transport type', _state.transportType);
}
break;
}
case '/meta/disconnect':
{
_state = null;
break;
}
default:
{
break;
}
}
return message;
};
this.incoming = function(message)
{
if (message.successful)
{
switch (message.channel)
{
case '/meta/handshake':
{
// If the handshake response is already present, then we're replaying it.
// Since the replay may have modified the handshake response, do not record it here.
if (!_state.handshakeResponse)
{
// Save successful handshake response
_state.handshakeResponse = message;
_debug('Reload extension tracked handshake response', message);
}
break;
}
case '/meta/disconnect':
{
_state = null;
break;
}
case '/meta/connect':
{
if (_batch)
{
_cometd.endBatch();
_batch = false;
}
break;
}
default:
{
break;
}
}
}
return message;
};
_configure(configuration);
};
}
if (typeof define === 'function' && define.amd)
{
define(['org/cometd'], bind);
}
else
{
bind(org.cometd);
}
})();

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2010 the original author or authors.
*
* 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.
*/
(function()
{
function bind(org_cometd)
{
/**
* The timestamp extension adds the optional timestamp field to all outgoing messages.
*/
return org_cometd.TimeStampExtension = function()
{
this.outgoing = function(message)
{
message.timestamp = new Date().toUTCString();
return message;
};
};
}
if (typeof define === 'function' && define.amd)
{
define(['org/cometd'], bind);
}
else
{
bind(org.cometd);
}
}());

View File

@ -0,0 +1,216 @@
/*
* Copyright (c) 2010 the original author or authors.
*
* 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.
*/
(function()
{
function bind(org_cometd)
{
/**
* With each handshake or connect, the extension sends timestamps within the
* ext field like: <code>{ext:{timesync:{tc:12345567890,l:23,o:4567},...},...}</code>
* where:<ul>
* <li>tc is the client timestamp in ms since 1970 of when the message was sent.
* <li>l is the network lag that the client has calculated.
* <li>o is the clock offset that the client has calculated.
* </ul>
*
* <p>
* A cometd server that supports timesync, can respond with an ext
* field like: <code>{ext:{timesync:{tc:12345567890,ts:1234567900,p:123,a:3},...},...}</code>
* where:<ul>
* <li>tc is the client timestamp of when the message was sent,
* <li>ts is the server timestamp of when the message was received
* <li>p is the poll duration in ms - ie the time the server took before sending the response.
* <li>a is the measured accuracy of the calculated offset and lag sent by the client
* </ul>
*
* <p>
* The relationship between tc, ts & l is given by <code>ts=tc+o+l</code> (the
* time the server received the messsage is the client time plus the offset plus the
* network lag). Thus the accuracy of the o and l settings can be determined with
* <code>a=(tc+o+l)-ts</code>.
* </p>
* <p>
* When the client has received the response, it can make a more accurate estimate
* of the lag as <code>l2=(now-tc-p)/2</code> (assuming symmetric lag).
* A new offset can then be calculated with the relationship on the client
* that <code>ts=tc+o2+l2</code>, thus <code>o2=ts-tc-l2</code>.
* </p>
* <p>
* Since the client also receives the a value calculated on the server, it
* should be possible to analyse this and compensate for some asymmetry
* in the lag. But the current client does not do this.
* </p>
*
* @param configuration
*/
return org_cometd.TimeSyncExtension = function(configuration)
{
var _cometd;
var _maxSamples = configuration && configuration.maxSamples || 10;
var _lags = [];
var _offsets = [];
var _lag = 0;
var _offset = 0;
function _debug(text, args)
{
_cometd._debug(text, args);
}
this.registered = function(name, cometd)
{
_cometd = cometd;
_debug('TimeSyncExtension: executing registration callback');
};
this.unregistered = function()
{
_debug('TimeSyncExtension: executing unregistration callback');
_cometd = null;
_lags = [];
_offsets = [];
};
this.incoming = function(message)
{
var channel = message.channel;
if (channel && channel.indexOf('/meta/') === 0)
{
if (message.ext && message.ext.timesync)
{
var timesync = message.ext.timesync;
_debug('TimeSyncExtension: server sent timesync', timesync);
var now = new Date().getTime();
var l2 = (now - timesync.tc - timesync.p) / 2;
var o2 = timesync.ts - timesync.tc - l2;
_lags.push(l2);
_offsets.push(o2);
if (_offsets.length > _maxSamples)
{
_offsets.shift();
_lags.shift();
}
var samples = _offsets.length;
var lagsSum = 0;
var offsetsSum = 0;
for (var i = 0; i < samples; ++i)
{
lagsSum += _lags[i];
offsetsSum += _offsets[i];
}
_lag = parseInt((lagsSum / samples).toFixed());
_offset = parseInt((offsetsSum / samples).toFixed());
_debug('TimeSyncExtension: network lag', _lag, 'ms, time offset with server', _offset, 'ms', _lag, _offset);
}
}
return message;
};
this.outgoing = function(message)
{
var channel = message.channel;
if (channel && channel.indexOf('/meta/') === 0)
{
if (!message.ext)
{
message.ext = {};
}
message.ext.timesync = {
tc: new Date().getTime(),
l: _lag,
o: _offset
};
_debug('TimeSyncExtension: client sending timesync', org_cometd.JSON.toJSON(message.ext.timesync));
}
return message;
};
/**
* Get the estimated offset in ms from the clients clock to the
* servers clock. The server time is the client time plus the offset.
*/
this.getTimeOffset = function()
{
return _offset;
};
/**
* Get an array of multiple offset samples used to calculate
* the offset.
*/
this.getTimeOffsetSamples = function()
{
return _offsets;
};
/**
* Get the estimated network lag in ms from the client to the server.
*/
this.getNetworkLag = function()
{
return _lag;
};
/**
* Get the estimated server time in ms since the epoch.
*/
this.getServerTime = function()
{
return new Date().getTime() + _offset;
};
/**
*
* Get the estimated server time as a Date object
*/
this.getServerDate = function()
{
return new Date(this.getServerTime());
};
/**
* Set a timeout to expire at given time on the server.
* @param callback The function to call when the timer expires
* @param atServerTimeOrDate a js Time or Date object representing the
* server time at which the timeout should expire
*/
this.setTimeout = function(callback, atServerTimeOrDate)
{
var ts = (atServerTimeOrDate instanceof Date) ? atServerTimeOrDate.getTime() : (0 + atServerTimeOrDate);
var tc = ts - _offset;
var interval = tc - new Date().getTime();
if (interval <= 0)
{
interval = 1;
}
return org_cometd.Utils.setTimeout(_cometd, callback, interval);
};
};
}
if (typeof define === 'function' && define.amd)
{
define(['org/cometd'], bind);
}
else
{
bind(org.cometd);
}
})();

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2008-2014 the original author or authors.
*
* 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.
*/
(function()
{
function bind(AckExtension, cometd)
{
var result = new AckExtension();
cometd.registerExtension('ack', result);
return result;
}
if (typeof define === 'function' && define.amd)
{
define(['org/cometd/AckExtension', 'jquery.cometd'], bind);
}
else
{
bind(org.cometd.AckExtension, jQuery.cometd);
}
})();

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2008-2014 the original author or authors.
*
* 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.
*/
(function()
{
function bind(org_cometd, cookie, ReloadExtension, cometd)
{
// Remap cometd COOKIE functions to jquery cookie functions
// Avoid to set to undefined if the jquery cookie plugin is not present
if (cookie)
{
org_cometd.COOKIE.set = cookie;
org_cometd.COOKIE.get = cookie;
}
var result = new ReloadExtension();
cometd.registerExtension('reload', result);
return result;
}
if (typeof define === 'function' && define.amd)
{
define(['org/cometd', 'jquery.cookie', 'org/cometd/ReloadExtension', 'jquery.cometd'], bind);
}
else
{
bind(org.cometd, jQuery.cookie, org.cometd.ReloadExtension, jQuery.cometd);
}
})();

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2008-2014 the original author or authors.
*
* 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.
*/
(function()
{
function bind(TimeStampExtension, cometd)
{
var result = new TimeStampExtension();
cometd.registerExtension('timestamp', result);
return result;
}
if (typeof define === 'function' && define.amd)
{
define(['org/cometd/TimeStampExtension', 'jquery.cometd'], bind);
}
else
{
bind(org.cometd.TimeStampExtension, jQuery.cometd);
}
})();

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2008-2014 the original author or authors.
*
* 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.
*/
(function()
{
function bind(TimeSyncExtension, cometd)
{
var result = new TimeSyncExtension();
cometd.registerExtension('timesync', result);
return result;
}
if (typeof define === 'function' && define.amd)
{
define(['org/cometd/TimeSyncExtension', 'jquery.cometd'], bind);
}
else
{
bind(org.cometd.TimeSyncExtension, jQuery.cometd);
}
})();

View File

@ -0,0 +1,136 @@
/*
* Copyright (c) 2008-2014 the original author or authors.
*
* 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.
*/
(function()
{
function bind($, org_cometd)
{
// Remap cometd JSON functions to jquery JSON functions
org_cometd.JSON.toJSON = JSON.stringify;
org_cometd.JSON.fromJSON = JSON.parse;
function _setHeaders(xhr, headers)
{
if (headers)
{
for (var headerName in headers)
{
if (headerName.toLowerCase() === 'content-type')
{
continue;
}
xhr.setRequestHeader(headerName, headers[headerName]);
}
}
}
// Remap toolkit-specific transport calls
function LongPollingTransport()
{
var _super = new org_cometd.LongPollingTransport();
var that = org_cometd.Transport.derive(_super);
that.xhrSend = function(packet)
{
return $.ajax({
url: packet.url,
async: packet.sync !== true,
type: 'POST',
contentType: 'application/json;charset=UTF-8',
data: packet.body,
beforeSend: function(xhr)
{
// Has no effect if the request is not cross domain
// but if it is, allows cookies to be sent to the server.
xhr.withCredentials = true;
_setHeaders(xhr, packet.headers);
// Returning false will abort the XHR send
return true;
},
success: packet.onSuccess,
error: function(xhr, reason, exception)
{
packet.onError(reason, exception);
}
});
};
return that;
}
function CallbackPollingTransport()
{
var _super = new org_cometd.CallbackPollingTransport();
var that = org_cometd.Transport.derive(_super);
that.jsonpSend = function(packet)
{
$.ajax({
url: packet.url,
async: packet.sync !== true,
type: 'GET',
dataType: 'jsonp',
jsonp: 'jsonp',
data: {
// In callback-polling, the content must be sent via the 'message' parameter
message: packet.body
},
beforeSend: function(xhr)
{
_setHeaders(xhr, packet.headers);
// Returning false will abort the XHR send
return true;
},
success: packet.onSuccess,
error: function(xhr, reason, exception)
{
packet.onError(reason, exception);
}
});
};
return that;
}
$.Cometd = function(name)
{
var cometd = new org_cometd.Cometd(name);
// Registration order is important
if (org_cometd.WebSocket)
{
cometd.registerTransport('websocket', new org_cometd.WebSocketTransport());
}
cometd.registerTransport('long-polling', new LongPollingTransport());
cometd.registerTransport('callback-polling', new CallbackPollingTransport());
return cometd;
};
// The default cometd instance
$.cometd = new $.Cometd();
return $.cometd;
}
if (typeof define === 'function' && define.amd)
{
define(['jquery', 'org/cometd'], bind);
}
else
{
bind(jQuery, org.cometd);
}
})();