PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/tomcat-7.0.2/java/org/apache/coyote/ajp/AjpProtocol.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 508 lines | 337 code | 91 blank | 80 comment | 38 complexity | 0bb643290cf28bfc866a4d9a9ce1849a MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package org.apache.coyote.ajp;
  18. import java.net.InetAddress;
  19. import java.net.Socket;
  20. import java.net.URLEncoder;
  21. import java.util.Hashtable;
  22. import java.util.Iterator;
  23. import java.util.concurrent.ConcurrentHashMap;
  24. import java.util.concurrent.ConcurrentLinkedQueue;
  25. import java.util.concurrent.Executor;
  26. import java.util.concurrent.atomic.AtomicInteger;
  27. import java.util.concurrent.atomic.AtomicLong;
  28. import javax.management.MBeanRegistration;
  29. import javax.management.MBeanServer;
  30. import javax.management.ObjectName;
  31. import org.apache.coyote.ActionCode;
  32. import org.apache.coyote.Adapter;
  33. import org.apache.coyote.ProtocolHandler;
  34. import org.apache.coyote.RequestGroupInfo;
  35. import org.apache.coyote.RequestInfo;
  36. import org.apache.juli.logging.Log;
  37. import org.apache.juli.logging.LogFactory;
  38. import org.apache.tomcat.util.modeler.Registry;
  39. import org.apache.tomcat.util.net.JIoEndpoint;
  40. import org.apache.tomcat.util.net.SocketStatus;
  41. import org.apache.tomcat.util.net.SocketWrapper;
  42. import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
  43. import org.apache.tomcat.util.net.JIoEndpoint.Handler;
  44. import org.apache.tomcat.util.res.StringManager;
  45. /**
  46. * Abstract the protocol implementation, including threading, etc.
  47. * Processor is single threaded and specific to stream-based protocols,
  48. * will not fit Jk protocols like JNI.
  49. *
  50. * @author Remy Maucherat
  51. * @author Costin Manolache
  52. */
  53. public class AjpProtocol
  54. implements ProtocolHandler, MBeanRegistration {
  55. private static final Log log = LogFactory.getLog(AjpProtocol.class);
  56. /**
  57. * The string manager for this package.
  58. */
  59. protected static final StringManager sm =
  60. StringManager.getManager(Constants.Package);
  61. // ------------------------------------------------------------ Constructor
  62. public AjpProtocol() {
  63. cHandler = new AjpConnectionHandler(this);
  64. setSoLinger(Constants.DEFAULT_CONNECTION_LINGER);
  65. setSoTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);
  66. //setServerSoTimeout(Constants.DEFAULT_SERVER_SOCKET_TIMEOUT);
  67. setTcpNoDelay(Constants.DEFAULT_TCP_NO_DELAY);
  68. }
  69. // ----------------------------------------------------- Instance Variables
  70. protected ObjectName tpOname;
  71. protected ObjectName rgOname;
  72. /**
  73. * Associated java.io endpoint.
  74. */
  75. protected JIoEndpoint endpoint = new JIoEndpoint();
  76. /**
  77. * Configuration attributes.
  78. */
  79. protected Hashtable<String,Object> attributes =
  80. new Hashtable<String,Object>();
  81. /**
  82. * Adapter which will process the requests received by this endpoint.
  83. */
  84. private Adapter adapter;
  85. /**
  86. * Connection handler for AJP.
  87. */
  88. private AjpConnectionHandler cHandler;
  89. // --------------------------------------------------------- Public Methods
  90. /**
  91. * Pass config info
  92. */
  93. public void setAttribute(String name, Object value) {
  94. if (log.isTraceEnabled()) {
  95. log.trace(sm.getString("ajpprotocol.setattribute", name, value));
  96. }
  97. attributes.put(name, value);
  98. }
  99. public Object getAttribute(String key) {
  100. if (log.isTraceEnabled()) {
  101. log.trace(sm.getString("ajpprotocol.getattribute", key));
  102. }
  103. return attributes.get(key);
  104. }
  105. public Iterator<String> getAttributeNames() {
  106. return attributes.keySet().iterator();
  107. }
  108. /**
  109. * The adapter, used to call the connector
  110. */
  111. public void setAdapter(Adapter adapter) {
  112. this.adapter = adapter;
  113. }
  114. public Adapter getAdapter() {
  115. return adapter;
  116. }
  117. /** Start the protocol
  118. */
  119. public void init() throws Exception {
  120. endpoint.setName(getName());
  121. endpoint.setHandler(cHandler);
  122. try {
  123. endpoint.init();
  124. } catch (Exception ex) {
  125. log.error(sm.getString("ajpprotocol.endpoint.initerror"), ex);
  126. throw ex;
  127. }
  128. if (log.isInfoEnabled()) {
  129. log.info(sm.getString("ajpprotocol.init", getName()));
  130. }
  131. }
  132. public void start() throws Exception {
  133. if (this.domain != null ) {
  134. try {
  135. tpOname = new ObjectName
  136. (domain + ":" + "type=ThreadPool,name=" + getName());
  137. Registry.getRegistry(null, null)
  138. .registerComponent(endpoint, tpOname, null );
  139. } catch (Exception e) {
  140. log.error("Can't register threadpool" );
  141. }
  142. rgOname = new ObjectName
  143. (domain + ":type=GlobalRequestProcessor,name=" + getName());
  144. Registry.getRegistry(null, null).registerComponent
  145. (cHandler.global, rgOname, null);
  146. }
  147. try {
  148. endpoint.start();
  149. } catch (Exception ex) {
  150. log.error(sm.getString("ajpprotocol.endpoint.starterror"), ex);
  151. throw ex;
  152. }
  153. if (log.isInfoEnabled())
  154. log.info(sm.getString("ajpprotocol.start", getName()));
  155. }
  156. public void pause() throws Exception {
  157. try {
  158. endpoint.pause();
  159. } catch (Exception ex) {
  160. log.error(sm.getString("ajpprotocol.endpoint.pauseerror"), ex);
  161. throw ex;
  162. }
  163. if (log.isInfoEnabled())
  164. log.info(sm.getString("ajpprotocol.pause", getName()));
  165. }
  166. public void resume() throws Exception {
  167. try {
  168. endpoint.resume();
  169. } catch (Exception ex) {
  170. log.error(sm.getString("ajpprotocol.endpoint.resumeerror"), ex);
  171. throw ex;
  172. }
  173. if (log.isInfoEnabled())
  174. log.info(sm.getString("ajpprotocol.resume", getName()));
  175. }
  176. public void destroy() throws Exception {
  177. if (log.isInfoEnabled())
  178. log.info(sm.getString("ajpprotocol.stop", getName()));
  179. endpoint.destroy();
  180. if (tpOname!=null)
  181. Registry.getRegistry(null, null).unregisterComponent(tpOname);
  182. if (rgOname != null)
  183. Registry.getRegistry(null, null).unregisterComponent(rgOname);
  184. }
  185. // *
  186. public String getName() {
  187. String encodedAddr = "";
  188. if (getAddress() != null) {
  189. encodedAddr = "" + getAddress();
  190. if (encodedAddr.startsWith("/"))
  191. encodedAddr = encodedAddr.substring(1);
  192. encodedAddr = URLEncoder.encode(encodedAddr) + "-";
  193. }
  194. return ("ajp-" + encodedAddr + endpoint.getPort());
  195. }
  196. /**
  197. * Processor cache.
  198. */
  199. protected int processorCache = -1;
  200. public int getProcessorCache() { return this.processorCache; }
  201. public void setProcessorCache(int processorCache) { this.processorCache = processorCache; }
  202. public Executor getExecutor() { return endpoint.getExecutor(); }
  203. public void setExecutor(Executor executor) { endpoint.setExecutor(executor); }
  204. public int getMaxThreads() { return endpoint.getMaxThreads(); }
  205. public void setMaxThreads(int maxThreads) { endpoint.setMaxThreads(maxThreads); }
  206. public int getThreadPriority() { return endpoint.getThreadPriority(); }
  207. public void setThreadPriority(int threadPriority) { endpoint.setThreadPriority(threadPriority); }
  208. public int getBacklog() { return endpoint.getBacklog(); }
  209. public void setBacklog(int backlog) { endpoint.setBacklog(backlog); }
  210. public int getPort() { return endpoint.getPort(); }
  211. public void setPort(int port) { endpoint.setPort(port); }
  212. public InetAddress getAddress() { return endpoint.getAddress(); }
  213. public void setAddress(InetAddress ia) { endpoint.setAddress(ia); }
  214. public boolean getTcpNoDelay() { return endpoint.getTcpNoDelay(); }
  215. public void setTcpNoDelay(boolean tcpNoDelay) { endpoint.setTcpNoDelay(tcpNoDelay); }
  216. public int getSoLinger() { return endpoint.getSoLinger(); }
  217. public void setSoLinger(int soLinger) { endpoint.setSoLinger(soLinger); }
  218. public int getSoTimeout() { return endpoint.getSoTimeout(); }
  219. public void setSoTimeout(int soTimeout) { endpoint.setSoTimeout(soTimeout); }
  220. /**
  221. * Should authentication be done in the native webserver layer,
  222. * or in the Servlet container ?
  223. */
  224. protected boolean tomcatAuthentication = true;
  225. public boolean getTomcatAuthentication() { return tomcatAuthentication; }
  226. public void setTomcatAuthentication(boolean tomcatAuthentication) { this.tomcatAuthentication = tomcatAuthentication; }
  227. /**
  228. * Required secret.
  229. */
  230. protected String requiredSecret = null;
  231. public void setRequiredSecret(String requiredSecret) { this.requiredSecret = requiredSecret; }
  232. /**
  233. * AJP packet size.
  234. */
  235. protected int packetSize = Constants.MAX_PACKET_SIZE;
  236. public int getPacketSize() { return packetSize; }
  237. public void setPacketSize(int packetSize) {
  238. if(packetSize < Constants.MAX_PACKET_SIZE) {
  239. this.packetSize = Constants.MAX_PACKET_SIZE;
  240. } else {
  241. this.packetSize = packetSize;
  242. }
  243. }
  244. /**
  245. * The number of seconds Tomcat will wait for a subsequent request
  246. * before closing the connection.
  247. */
  248. protected int keepAliveTimeout = -1;
  249. public int getKeepAliveTimeout() { return keepAliveTimeout; }
  250. public void setKeepAliveTimeout(int timeout) { keepAliveTimeout = timeout; }
  251. // -------------------------------------- AjpConnectionHandler Inner Class
  252. protected static class AjpConnectionHandler implements Handler {
  253. protected AjpProtocol proto;
  254. protected AtomicLong registerCount = new AtomicLong(0);
  255. protected RequestGroupInfo global = new RequestGroupInfo();
  256. protected ConcurrentHashMap<SocketWrapper<Socket>, AjpProcessor> connections =
  257. new ConcurrentHashMap<SocketWrapper<Socket>, AjpProcessor>();
  258. protected ConcurrentLinkedQueue<AjpProcessor> recycledProcessors =
  259. new ConcurrentLinkedQueue<AjpProcessor>() {
  260. protected AtomicInteger size = new AtomicInteger(0);
  261. @Override
  262. public boolean offer(AjpProcessor processor) {
  263. boolean offer = (proto.processorCache == -1) ? true : (size.get() < proto.processorCache);
  264. //avoid over growing our cache or add after we have stopped
  265. boolean result = false;
  266. if ( offer ) {
  267. result = super.offer(processor);
  268. if ( result ) {
  269. size.incrementAndGet();
  270. }
  271. }
  272. if (!result) unregister(processor);
  273. return result;
  274. }
  275. @Override
  276. public AjpProcessor poll() {
  277. AjpProcessor result = super.poll();
  278. if ( result != null ) {
  279. size.decrementAndGet();
  280. }
  281. return result;
  282. }
  283. @Override
  284. public void clear() {
  285. AjpProcessor next = poll();
  286. while ( next != null ) {
  287. unregister(next);
  288. next = poll();
  289. }
  290. super.clear();
  291. size.set(0);
  292. }
  293. };
  294. public AjpConnectionHandler(AjpProtocol proto) {
  295. this.proto = proto;
  296. }
  297. public SocketState process(SocketWrapper<Socket> socket) {
  298. return process(socket,SocketStatus.OPEN);
  299. }
  300. public SocketState process(SocketWrapper<Socket> socket, SocketStatus status) {
  301. AjpProcessor processor = connections.remove(socket);
  302. try {
  303. if (processor == null) {
  304. processor = recycledProcessors.poll();
  305. }
  306. if (processor == null) {
  307. processor = createProcessor();
  308. }
  309. processor.action(ActionCode.ACTION_START, null);
  310. SocketState state = socket.isAsync()?processor.asyncDispatch(status):processor.process(socket);
  311. if (state == SocketState.LONG) {
  312. connections.put(socket, processor);
  313. socket.setAsync(true);
  314. } else {
  315. connections.remove(socket);
  316. socket.setAsync(false);
  317. }
  318. return state;
  319. } catch(java.net.SocketException e) {
  320. // SocketExceptions are normal
  321. AjpProtocol.log.debug
  322. (sm.getString
  323. ("ajpprotocol.proto.socketexception.debug"), e);
  324. } catch (java.io.IOException e) {
  325. // IOExceptions are normal
  326. AjpProtocol.log.debug
  327. (sm.getString
  328. ("ajpprotocol.proto.ioexception.debug"), e);
  329. }
  330. // Future developers: if you discover any other
  331. // rare-but-nonfatal exceptions, catch them here, and log as
  332. // above.
  333. catch (Throwable e) {
  334. // any other exception or error is odd. Here we log it
  335. // with "ERROR" level, so it will show up even on
  336. // less-than-verbose logs.
  337. AjpProtocol.log.error
  338. (sm.getString("ajpprotocol.proto.error"), e);
  339. } finally {
  340. processor.action(ActionCode.ACTION_STOP, null);
  341. recycledProcessors.offer(processor);
  342. }
  343. return SocketState.CLOSED;
  344. }
  345. protected AjpProcessor createProcessor() {
  346. AjpProcessor processor = new AjpProcessor(proto.packetSize, proto.endpoint);
  347. processor.setAdapter(proto.adapter);
  348. processor.setTomcatAuthentication(proto.tomcatAuthentication);
  349. processor.setRequiredSecret(proto.requiredSecret);
  350. processor.setKeepAliveTimeout(proto.keepAliveTimeout);
  351. register(processor);
  352. return processor;
  353. }
  354. protected void register(AjpProcessor processor) {
  355. if (proto.getDomain() != null) {
  356. synchronized (this) {
  357. try {
  358. long count = registerCount.incrementAndGet();
  359. RequestInfo rp = processor.getRequest().getRequestProcessor();
  360. rp.setGlobalProcessor(global);
  361. ObjectName rpName = new ObjectName
  362. (proto.getDomain() + ":type=RequestProcessor,worker="
  363. + proto.getName() + ",name=AjpRequest" + count);
  364. if (log.isDebugEnabled()) {
  365. log.debug("Register " + rpName);
  366. }
  367. Registry.getRegistry(null, null).registerComponent(rp, rpName, null);
  368. rp.setRpName(rpName);
  369. } catch (Exception e) {
  370. log.warn("Error registering request");
  371. }
  372. }
  373. }
  374. }
  375. protected void unregister(AjpProcessor processor) {
  376. if (proto.getDomain() != null) {
  377. synchronized (this) {
  378. try {
  379. RequestInfo rp = processor.getRequest().getRequestProcessor();
  380. rp.setGlobalProcessor(null);
  381. ObjectName rpName = rp.getRpName();
  382. if (log.isDebugEnabled()) {
  383. log.debug("Unregister " + rpName);
  384. }
  385. Registry.getRegistry(null, null).unregisterComponent(rpName);
  386. rp.setRpName(null);
  387. } catch (Exception e) {
  388. log.warn("Error unregistering request", e);
  389. }
  390. }
  391. }
  392. }
  393. }
  394. // -------------------- Various implementation classes --------------------
  395. protected String domain;
  396. protected ObjectName oname;
  397. protected MBeanServer mserver;
  398. public ObjectName getObjectName() {
  399. return oname;
  400. }
  401. public String getDomain() {
  402. return domain;
  403. }
  404. public ObjectName preRegister(MBeanServer server,
  405. ObjectName name) throws Exception {
  406. oname=name;
  407. mserver=server;
  408. domain=name.getDomain();
  409. return name;
  410. }
  411. public void postRegister(Boolean registrationDone) {
  412. }
  413. public void preDeregister() throws Exception {
  414. }
  415. public void postDeregister() {
  416. }
  417. }