PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/qpid-0.16/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java

#
Java | 501 lines | 404 code | 66 blank | 31 comment | 38 complexity | e4770419a3c6bb7bbbc418521c138ea5 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1
  1. /*
  2. *
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. *
  20. */
  21. package org.apache.qpid.server.transport;
  22. import org.apache.qpid.AMQException;
  23. import org.apache.qpid.protocol.AMQConstant;
  24. import org.apache.qpid.server.configuration.ConnectionConfig;
  25. import org.apache.qpid.server.logging.LogActor;
  26. import org.apache.qpid.server.logging.LogSubject;
  27. import org.apache.qpid.server.logging.actors.CurrentActor;
  28. import org.apache.qpid.server.logging.actors.GenericActor;
  29. import org.apache.qpid.server.logging.messages.ConnectionMessages;
  30. import org.apache.qpid.server.management.Managable;
  31. import org.apache.qpid.server.management.ManagedObject;
  32. import org.apache.qpid.server.protocol.AMQConnectionModel;
  33. import org.apache.qpid.server.protocol.AMQSessionModel;
  34. import org.apache.qpid.server.security.AuthorizationHolder;
  35. import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
  36. import org.apache.qpid.server.stats.StatisticsCounter;
  37. import org.apache.qpid.server.virtualhost.VirtualHost;
  38. import org.apache.qpid.transport.Connection;
  39. import org.apache.qpid.transport.ConnectionCloseCode;
  40. import org.apache.qpid.transport.ExecutionErrorCode;
  41. import org.apache.qpid.transport.ExecutionException;
  42. import org.apache.qpid.transport.Method;
  43. import org.apache.qpid.transport.ProtocolEvent;
  44. import org.apache.qpid.transport.Session;
  45. import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CONNECTION_FORMAT;
  46. import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SOCKET_FORMAT;
  47. import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.USER_FORMAT;
  48. import javax.management.JMException;
  49. import javax.security.auth.Subject;
  50. import java.security.Principal;
  51. import java.text.MessageFormat;
  52. import java.util.ArrayList;
  53. import java.util.List;
  54. import java.util.UUID;
  55. import java.util.concurrent.atomic.AtomicBoolean;
  56. import java.util.concurrent.atomic.AtomicLong;
  57. public class ServerConnection extends Connection implements Managable, AMQConnectionModel, LogSubject, AuthorizationHolder
  58. {
  59. private ConnectionConfig _config;
  60. private Runnable _onOpenTask;
  61. private AtomicBoolean _logClosed = new AtomicBoolean(false);
  62. private LogActor _actor = GenericActor.getInstance(this);
  63. private Subject _authorizedSubject = null;
  64. private Principal _authorizedPrincipal = null;
  65. private boolean _statisticsEnabled = false;
  66. private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
  67. private final long _connectionId;
  68. private final Object _reference = new Object();
  69. private ServerConnectionMBean _mBean;
  70. private VirtualHost _virtualHost;
  71. private AtomicLong _lastIoTime = new AtomicLong();
  72. public ServerConnection(final long connectionId)
  73. {
  74. _connectionId = connectionId;
  75. }
  76. public UUID getId()
  77. {
  78. return _config.getId();
  79. }
  80. public Object getReference()
  81. {
  82. return _reference;
  83. }
  84. @Override
  85. protected void invoke(Method method)
  86. {
  87. super.invoke(method);
  88. }
  89. @Override
  90. protected void setState(State state)
  91. {
  92. super.setState(state);
  93. if (state == State.OPEN)
  94. {
  95. if (_onOpenTask != null)
  96. {
  97. _onOpenTask.run();
  98. }
  99. _actor.message(ConnectionMessages.OPEN(getClientId(), "0-10", getClientVersion(), true, true, true));
  100. getVirtualHost().getConnectionRegistry().registerConnection(this);
  101. }
  102. if (state == State.CLOSE_RCVD || state == State.CLOSED || state == State.CLOSING)
  103. {
  104. if(_virtualHost != null)
  105. {
  106. _virtualHost.getConnectionRegistry().deregisterConnection(this);
  107. }
  108. unregisterConnectionMbean();
  109. }
  110. if (state == State.CLOSED)
  111. {
  112. logClosed();
  113. }
  114. }
  115. protected void logClosed()
  116. {
  117. if(_logClosed.compareAndSet(false, true))
  118. {
  119. CurrentActor.get().message(this, ConnectionMessages.CLOSE());
  120. }
  121. }
  122. @Override
  123. public ServerConnectionDelegate getConnectionDelegate()
  124. {
  125. return (ServerConnectionDelegate) super.getConnectionDelegate();
  126. }
  127. public void setConnectionDelegate(ServerConnectionDelegate delegate)
  128. {
  129. super.setConnectionDelegate(delegate);
  130. }
  131. public VirtualHost getVirtualHost()
  132. {
  133. return _virtualHost;
  134. }
  135. public void setVirtualHost(VirtualHost virtualHost)
  136. {
  137. _virtualHost = virtualHost;
  138. initialiseStatistics();
  139. registerConnectionMbean();
  140. }
  141. public void setConnectionConfig(final ConnectionConfig config)
  142. {
  143. _config = config;
  144. }
  145. public ConnectionConfig getConfig()
  146. {
  147. return _config;
  148. }
  149. public void onOpen(final Runnable task)
  150. {
  151. _onOpenTask = task;
  152. }
  153. public void closeSession(AMQSessionModel session, AMQConstant cause, String message) throws AMQException
  154. {
  155. ExecutionException ex = new ExecutionException();
  156. ExecutionErrorCode code = ExecutionErrorCode.INTERNAL_ERROR;
  157. try
  158. {
  159. code = ExecutionErrorCode.get(cause.getCode());
  160. }
  161. catch (IllegalArgumentException iae)
  162. {
  163. // Ignore, already set to INTERNAL_ERROR
  164. }
  165. ex.setErrorCode(code);
  166. ex.setDescription(message);
  167. ((ServerSession)session).invoke(ex);
  168. ((ServerSession)session).close();
  169. }
  170. public LogSubject getLogSubject()
  171. {
  172. return (LogSubject) this;
  173. }
  174. @Override
  175. public void received(ProtocolEvent event)
  176. {
  177. _lastIoTime.set(System.currentTimeMillis());
  178. if (event.isConnectionControl())
  179. {
  180. CurrentActor.set(_actor);
  181. }
  182. else
  183. {
  184. ServerSession channel = (ServerSession) getSession(event.getChannel());
  185. LogActor channelActor = null;
  186. if (channel != null)
  187. {
  188. channelActor = channel.getLogActor();
  189. }
  190. CurrentActor.set(channelActor == null ? _actor : channelActor);
  191. }
  192. try
  193. {
  194. super.received(event);
  195. }
  196. finally
  197. {
  198. CurrentActor.remove();
  199. }
  200. }
  201. public String toLogString()
  202. {
  203. boolean hasVirtualHost = (null != this.getVirtualHost());
  204. boolean hasClientId = (null != getClientId());
  205. if (hasClientId && hasVirtualHost)
  206. {
  207. return "[" +
  208. MessageFormat.format(CONNECTION_FORMAT,
  209. getConnectionId(),
  210. getClientId(),
  211. getConfig().getAddress(),
  212. getVirtualHost().getName())
  213. + "] ";
  214. }
  215. else if (hasClientId)
  216. {
  217. return "[" +
  218. MessageFormat.format(USER_FORMAT,
  219. getConnectionId(),
  220. getClientId(),
  221. getConfig().getAddress())
  222. + "] ";
  223. }
  224. else
  225. {
  226. return "[" +
  227. MessageFormat.format(SOCKET_FORMAT,
  228. getConnectionId(),
  229. getConfig().getAddress())
  230. + "] ";
  231. }
  232. }
  233. public LogActor getLogActor()
  234. {
  235. return _actor;
  236. }
  237. public void close(AMQConstant cause, String message) throws AMQException
  238. {
  239. closeSubscriptions();
  240. unregisterConnectionMbean();
  241. ConnectionCloseCode replyCode = ConnectionCloseCode.NORMAL;
  242. try
  243. {
  244. replyCode = ConnectionCloseCode.get(cause.getCode());
  245. }
  246. catch (IllegalArgumentException iae)
  247. {
  248. // Ignore
  249. }
  250. close(replyCode, message);
  251. }
  252. public List<AMQSessionModel> getSessionModels()
  253. {
  254. List<AMQSessionModel> sessions = new ArrayList<AMQSessionModel>();
  255. for (Session ssn : getChannels())
  256. {
  257. sessions.add((AMQSessionModel) ssn);
  258. }
  259. return sessions;
  260. }
  261. public void registerMessageDelivered(long messageSize)
  262. {
  263. if (isStatisticsEnabled())
  264. {
  265. _messagesDelivered.registerEvent(1L);
  266. _dataDelivered.registerEvent(messageSize);
  267. }
  268. _virtualHost.registerMessageDelivered(messageSize);
  269. }
  270. public void registerMessageReceived(long messageSize, long timestamp)
  271. {
  272. if (isStatisticsEnabled())
  273. {
  274. _messagesReceived.registerEvent(1L, timestamp);
  275. _dataReceived.registerEvent(messageSize, timestamp);
  276. }
  277. _virtualHost.registerMessageReceived(messageSize, timestamp);
  278. }
  279. public StatisticsCounter getMessageReceiptStatistics()
  280. {
  281. return _messagesReceived;
  282. }
  283. public StatisticsCounter getDataReceiptStatistics()
  284. {
  285. return _dataReceived;
  286. }
  287. public StatisticsCounter getMessageDeliveryStatistics()
  288. {
  289. return _messagesDelivered;
  290. }
  291. public StatisticsCounter getDataDeliveryStatistics()
  292. {
  293. return _dataDelivered;
  294. }
  295. public void resetStatistics()
  296. {
  297. _messagesDelivered.reset();
  298. _dataDelivered.reset();
  299. _messagesReceived.reset();
  300. _dataReceived.reset();
  301. }
  302. public void initialiseStatistics()
  303. {
  304. setStatisticsEnabled(!StatisticsCounter.DISABLE_STATISTICS &&
  305. _virtualHost.getApplicationRegistry().getConfiguration().isStatisticsGenerationConnectionsEnabled());
  306. _messagesDelivered = new StatisticsCounter("messages-delivered-" + getConnectionId());
  307. _dataDelivered = new StatisticsCounter("data-delivered-" + getConnectionId());
  308. _messagesReceived = new StatisticsCounter("messages-received-" + getConnectionId());
  309. _dataReceived = new StatisticsCounter("data-received-" + getConnectionId());
  310. }
  311. public boolean isStatisticsEnabled()
  312. {
  313. return _statisticsEnabled;
  314. }
  315. public void setStatisticsEnabled(boolean enabled)
  316. {
  317. _statisticsEnabled = enabled;
  318. }
  319. /**
  320. * @return authorizedSubject
  321. */
  322. public Subject getAuthorizedSubject()
  323. {
  324. return _authorizedSubject;
  325. }
  326. /**
  327. * Sets the authorized subject. It also extracts the UsernamePrincipal from the subject
  328. * and caches it for optimisation purposes.
  329. *
  330. * @param authorizedSubject
  331. */
  332. public void setAuthorizedSubject(final Subject authorizedSubject)
  333. {
  334. if (authorizedSubject == null)
  335. {
  336. _authorizedSubject = null;
  337. _authorizedPrincipal = null;
  338. }
  339. else
  340. {
  341. _authorizedSubject = authorizedSubject;
  342. _authorizedPrincipal = UsernamePrincipal.getUsernamePrincipalFromSubject(_authorizedSubject);
  343. }
  344. }
  345. public Principal getAuthorizedPrincipal()
  346. {
  347. return _authorizedPrincipal;
  348. }
  349. public long getConnectionId()
  350. {
  351. return _connectionId;
  352. }
  353. public boolean isSessionNameUnique(byte[] name)
  354. {
  355. return !super.hasSessionWithName(name);
  356. }
  357. public String getUserName()
  358. {
  359. return _authorizedPrincipal.getName();
  360. }
  361. @Override
  362. public void closed()
  363. {
  364. closeSubscriptions();
  365. super.closed();
  366. }
  367. private void closeSubscriptions()
  368. {
  369. for (Session ssn : getChannels())
  370. {
  371. ((ServerSession)ssn).unregisterSubscriptions();
  372. }
  373. }
  374. public void receivedComplete()
  375. {
  376. for (Session ssn : getChannels())
  377. {
  378. ((ServerSession)ssn).receivedComplete();
  379. }
  380. }
  381. public ManagedObject getManagedObject()
  382. {
  383. return _mBean;
  384. }
  385. @Override
  386. public void send(ProtocolEvent event)
  387. {
  388. _lastIoTime.set(System.currentTimeMillis());
  389. super.send(event);
  390. }
  391. public AtomicLong getLastIoTime()
  392. {
  393. return _lastIoTime;
  394. }
  395. void checkForNotification()
  396. {
  397. int channelsCount = getSessionModels().size();
  398. if (_mBean != null && channelsCount >= getConnectionDelegate().getChannelMax())
  399. {
  400. _mBean.notifyClients("Channel count (" + channelsCount + ") has reached the threshold value");
  401. }
  402. }
  403. private void registerConnectionMbean()
  404. {
  405. try
  406. {
  407. _mBean = new ServerConnectionMBean(this);
  408. _mBean.register();
  409. }
  410. catch (JMException jme)
  411. {
  412. log.error("Unable to register mBean for ServerConnection", jme);
  413. }
  414. }
  415. private void unregisterConnectionMbean()
  416. {
  417. if (_mBean != null)
  418. {
  419. if (log.isDebugEnabled())
  420. {
  421. log.debug("Unregistering mBean for ServerConnection" + _mBean);
  422. }
  423. _mBean.unregister();
  424. _mBean = null;
  425. }
  426. }
  427. public String getClientId()
  428. {
  429. return getConnectionDelegate().getClientId();
  430. }
  431. public String getClientVersion()
  432. {
  433. return getConnectionDelegate().getClientVersion();
  434. }
  435. }