3 * A NetworkPackage class. This class implements the Deliverable class because
4 * all network packages should be deliverable to other nodes. It further
5 * provides methods for reading raw content from template engines and feeding it
6 * to the stacker for undeclared packages.
8 * The factory method requires you to provide a compressor class (which must
9 * implement the Compressor interface). If you don't want any compression (not
10 * adviceable due to increased network load), please use the NullCompressor
11 * class and encode it with BASE64 for a more error-free transfer over the
14 * For performance reasons, this class should only be instantiated once and then
15 * used as a "pipe-through" class.
17 * @author Roland Haeder <webmaster@ship-simu.org>
19 * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009, 2010 Hub Developer Team
20 * @license GNU GPL 3.0 or any newer version
21 * @link http://www.ship-simu.org
22 * @todo Needs to add functionality for handling the object's type
24 * This program is free software: you can redistribute it and/or modify
25 * it under the terms of the GNU General Public License as published by
26 * the Free Software Foundation, either version 3 of the License, or
27 * (at your option) any later version.
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
34 * You should have received a copy of the GNU General Public License
35 * along with this program. If not, see <http://www.gnu.org/licenses/>.
37 class NetworkPackage extends BaseFrameworkSystem implements Deliverable, Registerable {
39 * Package mask for compressing package data
41 const PACKAGE_MASK = '%s:%s:%s';
44 * Stacker name for "undeclared" packages
46 const STACKER_NAME_UNDECLARED = 'undeclared';
49 * Network target (alias): 'upper hubs'
51 const NETWORK_TARGET_UPPER_HUBS = 'upper';
54 * Protected constructor
58 protected function __construct () {
59 // Call parent constructor
60 parent::__construct(__CLASS__);
62 // We need to initialize a stack here for our packages even those
63 // which have no recipient address and stamp... ;-)
64 $stackerInstance = ObjectFactory::createObjectByConfiguredName('package_stacker_class');
66 // At last, set it in this class
67 $this->setStackerInstance($stackerInstance);
71 * Creates an instance of this class
73 * @param $compressorInstance A Compressor instance for compressing the content
74 * @return $packageInstance An instance of a Deliverable class
76 public final static function createNetworkPackage (Compressor $compressorInstance) {
78 $packageInstance = new NetworkPackage();
80 // Now set the compressor instance if set
81 if ($compressorInstance instanceof Compressor) {
83 $packageInstance->setCompressorInstance($compressorInstance);
86 // Return the prepared instance
87 return $packageInstance;
91 * "Enqueues" raw content into this delivery class by reading the raw content
92 * from given template instance and pushing it on the 'undeclared' stack.
94 * @param $helperInstance A BaseHubHelper instance
97 public function enqueueRawDataFromTemplate (BaseHubHelper $helperInstance) {
98 // Get the raw content ...
99 $content = $helperInstance->getTemplateInstance()->getRawTemplateData();
101 // ... and compress it
102 $content = $this->getCompressorInstance()->compressStream($content);
104 // Add magic in front of it and hash behind it, including BASE64 encoding
105 $content = sprintf(self::PACKAGE_MASK,
106 $this->getCompressorInstance()->getCompressorExtension(),
107 base64_encode($content),
108 crc32($content) // @TODO Not so good, but needs to be fast!
111 // Now prepare the temporary array and push it on the 'undeclared' stack
112 $this->getStackerInstance()->pushNamed(self::STACKER_NAME_UNDECLARED, array(
113 'sender' => $helperInstance->getNodeInstance()->getSessionId(),
114 'recipient' => self::NETWORK_TARGET_UPPER_HUBS,
115 'content' => $content,
120 * Checks wether a package has been enqueued for delivery.
122 * @return $isEnqueued Wether a package is enqueued
124 public function isPackageEnqueued () {
125 // Check wether the stacker is not empty
126 $isEnqueued = (($this->getStackerInstance()->isStackInitialized(self::STACKER_NAME_UNDECLARED)) && (!$this->getStackerInstance()->isStackEmpty(self::STACKER_NAME_UNDECLARED)));
133 * Delivers an enqueued package to the stated destination. If a non-session
134 * id is provided, recipient resolver is being asked (and instanced once).
135 * This allows that a single package is being delivered to multiple targets
136 * without enqueueing it for every target. If no target is provided or it
137 * can't be determined a NoTargetException is being thrown.
140 * @throws NoTargetException If no target can't be determined
142 public function deliverEnqueuedPackage () {
143 // Make sure this method isn't working if there is no package enqueued
144 if (!$this->isPackageEnqueued()) {
145 // This is not fatal but should be avoided
146 // @TODO Add some logging here
150 // Now we know for sure there are packages to deliver, we can start
151 // with the first one.
152 $packageData = $this->getStackerInstance()->getNamed(self::STACKER_NAME_UNDECLARED);
153 die(print_r($packageData, true));
155 // And remove it finally
156 $this->getStackerInstance()->popNamed(self::STACKER_NAME_UNDECLARED);