blob: a64a9687c3c840699ee758d7798139ae51e4cb94 [file] [log] [blame]
Jens Geyere8ca73f2014-03-24 21:41:12 +02001<?php
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 * @package thrift.processor
21 */
22
23namespace Thrift;
24
Jens Geyer80014212014-04-01 21:24:27 +020025use Thrift\Exception\TException;
Jens Geyere8ca73f2014-03-24 21:41:12 +020026use Thrift\Protocol\TProtocol;
27use Thrift\Protocol\TMultiplexedProtocol;
Jens Geyere8ca73f2014-03-24 21:41:12 +020028use Thrift\Type\TMessageType;
29
30/**
31 * <code>TMultiplexedProcessor</code> is a Processor allowing
32 * a single <code>TServer</code> to provide multiple services.
33 *
34 * <p>To do so, you instantiate the processor and then register additional
35 * processors with it, as shown in the following example:</p>
36 *
37 * <blockquote><code>
38 * $processor = new TMultiplexedProcessor();
39 *
40 * processor->registerProcessor(
41 * "Calculator",
42 * new \tutorial\CalculatorProcessor(new CalculatorHandler()));
43 *
44 * processor->registerProcessor(
45 * "WeatherReport",
46 * new \tutorial\WeatherReportProcessor(new WeatherReportHandler()));
47 *
48 * $processor->process($protocol, $protocol);
49 * </code></blockquote>
50 */
51
Roger Thomas6fb59232014-11-04 10:09:23 +000052class TMultiplexedProcessor
53{
Jens Geyere8ca73f2014-03-24 21:41:12 +020054 private $serviceProcessorMap_;
55
56 /**
57 * 'Register' a service with this <code>TMultiplexedProcessor</code>. This
58 * allows us to broker requests to individual services by using the service
59 * name to select them at request time.
60 *
61 * @param serviceName Name of a service, has to be identical to the name
62 * declared in the Thrift IDL, e.g. "WeatherReport".
Konrad Grochowski3b5dacb2014-11-24 10:55:31 +010063 * @param processor Implementation of a service, usually referred to
Jens Geyere8ca73f2014-03-24 21:41:12 +020064 * as "handlers", e.g. WeatherReportHandler implementing WeatherReport.Iface.
65 */
Roger Thomas6fb59232014-11-04 10:09:23 +000066 public function registerProcessor($serviceName, $processor)
67 {
Jens Geyere8ca73f2014-03-24 21:41:12 +020068 $this->serviceProcessorMap_[$serviceName] = $processor;
69 }
70
71 /**
72 * This implementation of <code>process</code> performs the following steps:
73 *
74 * <ol>
75 * <li>Read the beginning of the message.</li>
76 * <li>Extract the service name from the message.</li>
77 * <li>Using the service name to locate the appropriate processor.</li>
78 * <li>Dispatch to the processor, with a decorated instance of TProtocol
79 * that allows readMessageBegin() to return the original Message.</li>
80 * </ol>
81 *
82 * @throws TException If the message type is not CALL or ONEWAY, if
Roger Thomas6fb59232014-11-04 10:09:23 +000083 * the service name was not found in the message, or if the service
84 * name was not found in the service map.
Jens Geyere8ca73f2014-03-24 21:41:12 +020085 */
Roger Thomas6fb59232014-11-04 10:09:23 +000086 public function process(TProtocol $input, TProtocol $output)
87 {
Jens Geyere8ca73f2014-03-24 21:41:12 +020088 /*
89 Use the actual underlying protocol (e.g. TBinaryProtocol) to read the
90 message header. This pulls the message "off the wire", which we'll
91 deal with at the end of this method.
92 */
93 $input->readMessageBegin($fname, $mtype, $rseqid);
94
95 if ($mtype !== TMessageType::CALL && $mtype != TMessageType::ONEWAY) {
96 throw new TException("This should not have happened!?");
97 }
98
99 // Extract the service name and the new Message name.
100 if (strpos($fname, TMultiplexedProtocol::SEPARATOR) === false) {
101 throw new TException("Service name not found in message name: {$fname}. Did you " .
102 "forget to use a TMultiplexProtocol in your client?");
103 }
104 list($serviceName, $messageName) = explode(':', $fname, 2);
105 if (!array_key_exists($serviceName, $this->serviceProcessorMap_)) {
106 throw new TException("Service name not found: {$serviceName}. Did you forget " .
107 "to call registerProcessor()?");
108 }
109
110 // Dispatch processing to the stored processor
111 $processor = $this->serviceProcessorMap_[$serviceName];
Roger Thomas6fb59232014-11-04 10:09:23 +0000112
Jens Geyere8ca73f2014-03-24 21:41:12 +0200113 return $processor->process(
Robert Lub03ca012018-01-18 19:06:39 +0800114 new StoredMessageProtocol($input, $messageName, $mtype, $rseqid),
115 $output
Jens Geyere8ca73f2014-03-24 21:41:12 +0200116 );
117 }
118}