├── .gitignore ├── src ├── Exception │ └── PgsqlException.php ├── Contract │ ├── ConnectionInterface.php │ ├── DbSelectorInterface.php │ └── ConnectorInterface.php ├── Connection │ ├── PgsqlConnection.php │ ├── ConnectionManager.php │ └── Connection.php ├── AutoLoader.php ├── Pool.php ├── Pgsql.php ├── Connector │ └── PgsqlConnector.php └── PgsqlDb.php ├── .travis.yml ├── testing ├── AutoLoader.php └── bean.php ├── composer.json ├── README.md ├── run.php └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .buildpath 2 | .settings/ 3 | .project 4 | *.patch 5 | .idea/ 6 | .git/ 7 | runtime/ 8 | vendor/ 9 | temp/ 10 | *.lock 11 | .phpintel/ 12 | .DS_Store -------------------------------------------------------------------------------- /src/Exception/PgsqlException.php: -------------------------------------------------------------------------------- 1 | > ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini 12 | 13 | before_script: 14 | - composer config -g process-timeout 900 && composer update 15 | - phpenv config-rm xdebug.ini 16 | -------------------------------------------------------------------------------- /testing/AutoLoader.php: -------------------------------------------------------------------------------- 1 | __DIR__, 31 | ]; 32 | } 33 | } -------------------------------------------------------------------------------- /testing/bean.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'path' => __DIR__ . '/../config', 6 | ], 7 | 'pgsql' => [ 8 | 'class' => PgsqlDb::class, 9 | 'host' => '127.0.0.1', 10 | 'port' => 5432, 11 | 'database' => 'dbname', 12 | 'schema' => ['topology', 'public'], 13 | 'charset' => 'utf8', 14 | 'user' => 'user', 15 | 'password' => 'pass' 16 | ], 17 | 'pgsql.pool' => [ 18 | 'class' => \Swoft\Pgsql\Pool::class, 19 | 'pgsqlDb' => bean('pgsql'), 20 | 'minActive' => 2, 21 | 'mixActive' => 20, 22 | 'maxWait' => 0, 23 | 'maxWaitTime' => 0, 24 | 'maxIdleTime' => 60, 25 | ], 26 | ]; 27 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "curtis18/swoft-pgsql", 3 | "type": "library", 4 | "keywords": [ 5 | "php", 6 | "swoole", 7 | "swoft", 8 | "pgsql", 9 | "postgresql" 10 | ], 11 | "description": "swoft postgresql component", 12 | "license": "Apache-2.0", 13 | "require": { 14 | "swoft/framework": "~2.0.0", 15 | "swoft/connection-pool": "~2.0.0" 16 | }, 17 | "autoload": { 18 | "classmap": [ 19 | ], 20 | "psr-4": { 21 | "Swoft\\Pgsql\\": "src/" 22 | }, 23 | "files": [ 24 | ] 25 | }, 26 | "autoload-dev": { 27 | "psr-4": { 28 | "SwoftTest\\Pgsql\\Testing\\": "test/testing" 29 | } 30 | }, 31 | "require-dev": { 32 | "phpunit/phpunit": "^7.5" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/AutoLoader.php: -------------------------------------------------------------------------------- 1 | __DIR__, 27 | ]; 28 | } 29 | 30 | /** 31 | * @return array 32 | */ 33 | public function metadata(): array 34 | { 35 | return []; 36 | } 37 | 38 | /** 39 | * @return array 40 | * @throws ReflectionException 41 | * @throws ContainerException 42 | */ 43 | public function beans(): array 44 | { 45 | return [ 46 | 'pgsql' => [ 47 | 'class' => PgsqlDb::class, 48 | ], 49 | 'pgsql.pool' => [ 50 | 'class' => Pool::class, 51 | 'pgsqlDb' => bean('pgsql') 52 | ] 53 | ]; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Swoft PostgreSQL Component 2 | 3 | [![Latest Stable Version](http://img.shields.io/packagist/v/curtis18/swoft-pgsql.svg)](https://packagist.org/packages/curtis18/swoft-pgsql) 4 | [![PHP Version](https://img.shields.io/badge/php-%3E=7.1-brightgreen.svg?maxAge=2592000)](https://secure.php.net/) 5 | [![Swoft Doc](https://img.shields.io/badge/docs-passing-green.svg?maxAge=2592000)](https://www.swoft.org/docs) 6 | [![Swoft PostgreSQL Component License](https://img.shields.io/hexpm/l/plug.svg?maxAge=2592000)](https://github.com/curtis18/swoft-pgsql/blob/master/LICENSE) 7 | 8 | Swoft PostgreSQL Component 9 | 10 | ## Install 11 | 12 | - If you are using Swoole 4.4 or above, make sure install the extension of Swoole PostgreSQL. 13 | 14 | - composer command 15 | 16 | ```bash 17 | composer require curtis18/swoft-pgsql 18 | ``` 19 | 20 | ## Resources 21 | 22 | * [Documentation of Swoole PostgreSQL Extension](https://github.com/swoole/ext-postgresql) 23 | * [Documentation of Swoft](https://swoft.org/docs) 24 | * [Report Issues][issues] and [Send Pull Requests][pulls] in the [Main Swoft PostgreSQL Component Repository][repository] 25 | 26 | [pulls]: https://github.com/curtis18/swoft-pgsql/pulls 27 | [repository]: https://github.com/curtis18/swoft-pgsql 28 | [issues]: https://github.com/curtis18/swoft-pgsql/issues 29 | 30 | ## LICENSE 31 | 32 | The Component is open-sourced software licensed under the [Apache license](LICENSE). 33 | -------------------------------------------------------------------------------- /src/Pool.php: -------------------------------------------------------------------------------- 1 | pgsqlDb->getDbSelector(); 43 | 44 | /* @var Connection $connection select db */ 45 | if (!empty($dbSelector)) { 46 | $dbSelector->select($connection); 47 | } 48 | 49 | return $connection; 50 | } 51 | 52 | /** 53 | * Create connection 54 | * 55 | * @return ConnectionInterface 56 | * @throws ContainerException 57 | * @throws PgsqlException 58 | * @throws ReflectionException 59 | */ 60 | public function createConnection(): ConnectionInterface 61 | { 62 | return $this->pgsqlDb->createConnection($this); 63 | } 64 | 65 | /** 66 | * @return PgsqlDb 67 | */ 68 | public function getDatabase(): PgsqlDb 69 | { 70 | return $this->pgsqlDb; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Connection/ConnectionManager.php: -------------------------------------------------------------------------------- 1 | [ 24 | * 'cid' => [ 25 | * 'connectionId' => Connection 26 | * ] 27 | * ] 28 | * ] 29 | */ 30 | use DataPropertyTrait; 31 | 32 | /** 33 | * @param ConnectionInterface $connection 34 | */ 35 | public function setConnection(ConnectionInterface $connection): void 36 | { 37 | $key = sprintf('%d.%d.%d', Co::tid(), Co::id(), $connection->getId()); 38 | $this->set($key, $connection); 39 | } 40 | 41 | /** 42 | * @param int $id 43 | */ 44 | public function releaseConnection(int $id): void 45 | { 46 | $key = sprintf('%d.%d.%d', Co::tid(), Co::id(), $id); 47 | 48 | $this->unset($key); 49 | } 50 | 51 | /** 52 | * @param bool $final 53 | */ 54 | public function release(bool $final = false): void 55 | { 56 | $key = sprintf('%d.%d', Co::tid(), Co::id()); 57 | 58 | $connections = $this->get($key, []); 59 | foreach ($connections as $connection) { 60 | if ($connection instanceof ConnectionInterface) { 61 | $connection->release(); 62 | } 63 | } 64 | 65 | if ($final) { 66 | $finalKey = sprintf('%d', Co::tid()); 67 | $this->unset($finalKey); 68 | } 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /src/Pgsql.php: -------------------------------------------------------------------------------- 1 | getConnection(); 35 | 36 | $connection->setRelease(true); 37 | $conManager->setConnection($connection); 38 | } catch (Throwable $e) { 39 | throw new PgsqlException( 40 | sprintf('Pool error is %s file=%s line=%d', $e->getMessage(), $e->getFile(), $e->getLine()) 41 | ); 42 | } 43 | 44 | // Not instanceof Connection 45 | if (!$connection instanceof Connection) { 46 | throw new PgsqlException( 47 | sprintf('%s is not instanceof %s', get_class($connection), Connection::class) 48 | ); 49 | } 50 | return $connection; 51 | } 52 | 53 | /** 54 | * @param string $method 55 | * @param array $arguments 56 | * 57 | * @return mixed 58 | * @throws PgsqlException 59 | */ 60 | public static function __callStatic(string $method, array $arguments) 61 | { 62 | $connection = self::connection(); 63 | return $connection->{$method}(...$arguments); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /run.php: -------------------------------------------------------------------------------- 1 | SWOOLE_LOG_INFO, 8 | 'trace_flags' => 0 9 | ]); 10 | /* 11 | * This file is part of PHPUnit. 12 | * 13 | * (c) Sebastian Bergmann 14 | * 15 | * For the full copyright and license information, please view the LICENSE 16 | * file that was distributed with this source code. 17 | */ 18 | if (version_compare('7.1.0', PHP_VERSION, '>')) { 19 | fwrite( 20 | STDERR, 21 | sprintf( 22 | 'This version of PHPUnit is supported on PHP 7.1 and PHP 7.2.' . PHP_EOL . 23 | 'You are using PHP %s (%s).' . PHP_EOL, 24 | PHP_VERSION, 25 | PHP_BINARY 26 | ) 27 | ); 28 | die(1); 29 | } 30 | if (!ini_get('date.timezone')) { 31 | ini_set('date.timezone', 'UTC'); 32 | } 33 | foreach ([ 34 | __DIR__ . '/../../autoload.php', 35 | __DIR__ . '/../vendor/autoload.php', 36 | __DIR__ . '/vendor/autoload.php' 37 | ] as $file 38 | ) { 39 | if (file_exists($file)) { 40 | define('PHPUNIT_COMPOSER_INSTALL', $file); 41 | break; 42 | } 43 | } 44 | unset($file); 45 | if (!defined('PHPUNIT_COMPOSER_INSTALL')) { 46 | fwrite( 47 | STDERR, 48 | 'You need to set up the project dependencies using Composer:' . PHP_EOL . PHP_EOL . 49 | ' composer install' . PHP_EOL . PHP_EOL . 50 | 'You can learn all about Composer on https://getcomposer.org/.' . PHP_EOL 51 | ); 52 | die(1); 53 | } else { 54 | if (array_reverse(explode('/', __DIR__))[0] ?? '' === 'tests') { 55 | $vendor_dir = dirname(PHPUNIT_COMPOSER_INSTALL); 56 | $bin_unit = "{$vendor_dir}/bin/phpunit"; 57 | $unit_uint = "{$vendor_dir}/phpunit/phpunit/phpunit"; 58 | if (file_exists($bin_unit)) { 59 | @unlink($bin_unit); 60 | @symlink(__FILE__, $bin_unit); 61 | } 62 | if (file_exists($unit_uint)) { 63 | @unlink($unit_uint); 64 | @symlink(__FILE__, $unit_uint); 65 | } 66 | } 67 | } 68 | if (!in_array('-c', $_SERVER['argv'])) { 69 | $_SERVER['argv'][] = '-c'; 70 | $_SERVER['argv'][] = __DIR__ . '/phpunit.xml'; 71 | } 72 | require PHPUNIT_COMPOSER_INSTALL; 73 | 74 | $status = 0; 75 | go(function (){ 76 | // Status 77 | global $status; 78 | 79 | try { 80 | $status = PHPUnit\TextUI\Command::main(false); 81 | } catch (ExitException $e) { 82 | var_dump($e->getMessage()); 83 | $status = $e->getCode(); 84 | } 85 | }); 86 | 87 | 88 | Swoole\Event::wait(); 89 | 90 | exit($status); 91 | -------------------------------------------------------------------------------- /src/Connector/PgsqlConnector.php: -------------------------------------------------------------------------------- 1 | connect("host=".$config['host']." port=".$config['port']." dbname=".$config['database']." user=".$config['user']." password=".$config['password']); 36 | } catch (Throwable $e) { 37 | throw new PgsqlException( 38 | sprintf('Pgsql cannot be connected!') 39 | ); 40 | } 41 | 42 | if ($connection === false){ 43 | throw new PgsqlException( 44 | sprintf('Pgsql connection fail!') 45 | ); 46 | } else { 47 | if (!empty($config['schema'])){ 48 | $client->query("SET search_path TO ".implode(",", $config['schema']).";"); 49 | } else { 50 | $client->query("SET search_path TO public;"); 51 | } 52 | } 53 | 54 | return $client; 55 | } 56 | 57 | /** 58 | * @param array $config 59 | * 60 | * @return object 61 | * @throws Throwable 62 | */ 63 | public function pgConnect(array $config) 64 | { 65 | try { 66 | $connection = pg_connect("host=".$config['host']." port=".$config['port']." dbname=".$config['database']." user=".$config['user']." password=".$config['password']); 67 | } catch (Throwable $e) { 68 | throw new PgsqlException( 69 | sprintf('Pgsql cannot be connected!') 70 | ); 71 | } 72 | 73 | if ($connection === false){ 74 | throw new PgsqlException( 75 | sprintf('Pgsql connection fail!') 76 | ); 77 | } else { 78 | if (!empty($config['schema'])){ 79 | pg_query($connection, "SET search_path TO ".implode(",", $config['schema']).";"); 80 | } else { 81 | pg_query($connection, "SET search_path TO public;"); 82 | } 83 | } 84 | 85 | return $connection; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/PgsqlDb.php: -------------------------------------------------------------------------------- 1 | getConnection(); 107 | $connection->initialize($pool, $this); 108 | $connection->create(); 109 | 110 | return $connection; 111 | } 112 | 113 | /** 114 | * @return ConnectorInterface 115 | * @throws PgsqlException 116 | * @throws ReflectionException 117 | * @throws ContainerException 118 | */ 119 | public function getConnector(): ConnectorInterface 120 | { 121 | $connectors = Arr::merge($this->defaultConnectors(), $this->connectors); 122 | $connector = $connectors[$this->driver] ?? null; 123 | 124 | if (!$connector instanceof ConnectorInterface) { 125 | throw new PgsqlException(sprintf('Connector(dirver=%s) is not exist', $this->driver)); 126 | } 127 | 128 | return $connector; 129 | } 130 | 131 | /** 132 | * @return Connection 133 | * @throws PgsqlException 134 | * @throws ReflectionException 135 | * @throws ContainerException 136 | */ 137 | public function getConnection(): Connection 138 | { 139 | $connections = Arr::merge($this->defaultConnections(), $this->connections); 140 | $connection = $connections[$this->driver] ?? null; 141 | 142 | if (!$connection instanceof Connection) { 143 | throw new PgsqlException(sprintf('Connection(dirver=%s) is not exist', $this->driver)); 144 | } 145 | 146 | return $connection; 147 | } 148 | 149 | /** 150 | * @return DbSelectorInterface 151 | */ 152 | public function getDbSelector(): ?DbSelectorInterface 153 | { 154 | return $this->dbSelector; 155 | } 156 | 157 | /** 158 | * @return array 159 | * @throws ReflectionException 160 | * @throws ContainerException 161 | */ 162 | public function defaultConnectors(): array 163 | { 164 | return [ 165 | self::PHP_PGSQL => bean(PgsqlConnector::class) 166 | ]; 167 | } 168 | 169 | /** 170 | * @return array 171 | * @throws ReflectionException 172 | * @throws ContainerException 173 | */ 174 | public function defaultConnections(): array 175 | { 176 | return [ 177 | self::PHP_PGSQL => bean(PgsqlConnection::class) 178 | ]; 179 | } 180 | 181 | /** 182 | * @return string 183 | */ 184 | public function getDriver(): string 185 | { 186 | return $this->driver; 187 | } 188 | 189 | /** 190 | * @return string 191 | */ 192 | public function getHost(): string 193 | { 194 | return $this->host; 195 | } 196 | 197 | /** 198 | * @return int 199 | */ 200 | public function getPort(): int 201 | { 202 | return (int)$this->port; 203 | } 204 | 205 | /** 206 | * @return string 207 | */ 208 | public function getDatabase(): string 209 | { 210 | return (string)$this->database; 211 | } 212 | 213 | /** 214 | * @return string 215 | */ 216 | public function getSchema(): array 217 | { 218 | return $this->schema; 219 | } 220 | 221 | /** 222 | * @return string 223 | */ 224 | public function getUser(): string 225 | { 226 | return (string)$this->user; 227 | } 228 | 229 | /** 230 | * @return string 231 | */ 232 | public function getPassword(): string 233 | { 234 | return $this->password; 235 | } 236 | 237 | /** 238 | * @return float 239 | */ 240 | public function getTimeout(): float 241 | { 242 | return (int)$this->timeout; 243 | } 244 | 245 | /** 246 | * @return int 247 | */ 248 | public function getRetryInterval(): int 249 | { 250 | return (int)$this->retryInterval; 251 | } 252 | 253 | /** 254 | * @return int 255 | */ 256 | public function getReadTimeout(): int 257 | { 258 | return (int)$this->readTimeout; 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /src/Connection/Connection.php: -------------------------------------------------------------------------------- 1 | pool = $pool; 49 | $this->pgsqlDb = $pgsqlDb; 50 | $this->lastTime = time(); 51 | 52 | $this->id = $this->pool->getConnectionId(); 53 | } 54 | 55 | /** 56 | * @throws PgsqlException 57 | * @throws ReflectionException 58 | * @throws ContainerException 59 | */ 60 | public function create(): void 61 | { 62 | $this->createClient(); 63 | } 64 | 65 | /** 66 | * Close connection 67 | */ 68 | public function close(): void 69 | { 70 | $this->client->close(); 71 | } 72 | 73 | /** 74 | * Close Pg connection 75 | */ 76 | public function pgClose(): void 77 | { 78 | pg_close($this->pgresource); 79 | } 80 | 81 | /** 82 | * @param bool $boolPgResource 83 | * 84 | * @throws ReflectionException 85 | * @throws ContainerException 86 | * @throws PgsqlException 87 | */ 88 | public function createClient(bool $boolPgResource = false): void 89 | { 90 | $config = [ 91 | 'host' => $this->pgsqlDb->getHost(), 92 | 'port' => $this->pgsqlDb->getPort(), 93 | 'user' => $this->pgsqlDb->getUser(), 94 | 'password' => $this->pgsqlDb->getPassword(), 95 | 'database' => $this->pgsqlDb->getDatabase(), 96 | 'schema' => $this->pgsqlDb->getSchema(), 97 | 'timeout' => $this->pgsqlDb->getTimeout(), 98 | 'retry_interval' => $this->pgsqlDb->getRetryInterval(), 99 | 'read_timeout' => $this->pgsqlDb->getReadTimeout(), 100 | ]; 101 | 102 | if ($boolPgResource == false) { 103 | $this->client = $this->pgsqlDb->getConnector()->connect($config); 104 | } else { 105 | $this->pgresource = $this->pgsqlDb->getConnector()->pgConnect($config); 106 | } 107 | } 108 | 109 | /** 110 | * @param bool $force 111 | * 112 | * @throws ReflectionException 113 | * @throws ContainerException 114 | */ 115 | public function release(bool $force = false): void 116 | { 117 | /* @var ConnectionManager $conManager */ 118 | $conManager = BeanFactory::getBean(ConnectionManager::class); 119 | $conManager->releaseConnection($this->id); 120 | 121 | parent::release($force); 122 | } 123 | 124 | /** 125 | * @return bool 126 | * @throws ContainerException 127 | * @throws ReflectionException 128 | */ 129 | public function reconnect(): bool 130 | { 131 | try { 132 | $this->create(); 133 | } catch (Throwable $e) { 134 | Log::error('Pgsql reconnect error(%s)', $e->getMessage()); 135 | return false; 136 | } 137 | 138 | return true; 139 | } 140 | 141 | /** 142 | * Reconnect to the database if a connection is missing. 143 | * 144 | * @return void 145 | */ 146 | protected function reconnectIfMissingConnection() 147 | { 148 | if (is_null($this->client)) { 149 | $this->reconnect(); 150 | } 151 | } 152 | 153 | /** 154 | * Run a query statement against the database. 155 | * 156 | * @param string $query 157 | * @param array $bindings 158 | * 159 | * @return array 160 | * @throws ContainerException 161 | * @throws DbException 162 | * @throws ReflectionException 163 | */ 164 | public function select(string $query, array $bindings = []): array 165 | { 166 | $this->reconnectIfMissingConnection(); 167 | 168 | if (empty($bindings)) { 169 | $resource = $this->client->query($query); 170 | } else { 171 | $hash = md5($query); 172 | $prepare = $this->client->prepare("query_".$hash, $query); 173 | $resource = $this->client->execute("query_".$hash, $bindings); 174 | } 175 | 176 | $output = $this->client->fetchAll($resource); 177 | 178 | return ($output == false) ? [] : $output; 179 | } 180 | 181 | /** 182 | * Run a select statement and return value array without key 183 | * 184 | * @param string $query 185 | * @param array $bindings 186 | * 187 | * @return array 188 | * @throws ContainerException 189 | * @throws DbException 190 | * @throws ReflectionException 191 | */ 192 | public function selectFetchNum(string $query, array $bindings = []): array 193 | { 194 | $values = []; 195 | $output = $this->select($query, $bindings); 196 | 197 | foreach($output as $rows) { 198 | $values[] = array_values($rows); 199 | } 200 | return $values; 201 | } 202 | 203 | /** 204 | * Copy a table and return value array 205 | * 206 | * @param string $table_name 207 | * @param string $delimiter 208 | * @param string $null_as 209 | * 210 | * @return array 211 | * @throws ContainerException 212 | * @throws DbException 213 | * @throws ReflectionException 214 | */ 215 | public function copyTo(string $table_name, string $delimiter = "|", string $null_as = "\\NULL"): array 216 | { 217 | $this->createClient(true); 218 | $result = pg_copy_to($this->pgresource, $table_name, $delimiter, $null_as); 219 | $this->pgClose(); 220 | return ($result === false) ? [] : $result; 221 | } 222 | 223 | /** 224 | * Import array value into a table and return bool 225 | * 226 | * @param string $table_name 227 | * @param array $rows 228 | * @param string $delimiter 229 | * @param string $null_as 230 | * 231 | * @return bool 232 | * @throws ContainerException 233 | * @throws DbException 234 | * @throws ReflectionException 235 | */ 236 | public function copyFrom(string $table_name, array $rows, string $delimiter = "|", string $null_as = "\\NULL"): bool 237 | { 238 | $this->createClient(true); 239 | $result = pg_copy_from($this->pgresource, $table_name, $rows, $delimiter, $null_as); 240 | $this->pgClose(); 241 | return $result; 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------