/** * Provisions all web applications. * * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance * * @return void */ public function provision(ApplicationInterface $application) { // check if the webapps directory exists if (is_dir($webappPath = $application->getWebappPath())) { // prepare the glob expression with the application's directories to parse $applicationDirectories = AppEnvironmentHelper::getEnvironmentAwareGlobPattern($webappPath, '{WEB-INF,META-INF}/provision', GLOB_BRACE); // load the service instance /** @var \AppserverIo\Appserver\Core\Api\ProvisioningService $service */ $service = $this->getService(); // load the configuration service instance /** @var \AppserverIo\Appserver\Core\Api\ConfigurationService $configurationService */ $configurationService = $this->getInitialContext()->newService('AppserverIo\\Appserver\\Core\\Api\\ConfigurationService'); // load the container node to initialize the system properties /** @var \AppserverIo\Appserver\Core\Api\Node\ContainerNodeInterface $containerNode */ $containerNode = $application->getContainer()->getContainerNode(); // iterate through all provisioning files (provision.xml), validate them and attach them to the configuration foreach ($service->globDir($applicationDirectories, GLOB_BRACE) as $provisionFile) { try { // validate the file, but skip it if the validation fails $configurationService->validateFile($provisionFile, null); // load the system properties $properties = $service->getSystemProperties($containerNode); // append the application specific properties $properties->add(SystemPropertyKeys::WEBAPP, $webappPath); $properties->add(SystemPropertyKeys::WEBAPP_NAME, basename($webappPath)); $properties->add(SystemPropertyKeys::WEBAPP_CACHE, $application->getCacheDir()); $properties->add(SystemPropertyKeys::WEBAPP_SESSION, $application->getSessionDir()); // create a new provision node instance and replace the properties $provisionNode = new ProvisionNode(); $provisionNode->initFromFile($provisionFile); $provisionNode->replaceProperties($properties); // query whether we've a datasource configured or not if ($datasource = $provisionNode->getDatasource()) { // try to load the datasource from the system configuration $datasourceNode = $service->findByName($datasource->getName()); // try to inject the datasource node if available if ($datasourceNode != null) { $provisionNode->injectDatasource($datasourceNode); } } /* Re-provision the provision.xml (reinitialize). * * ATTENTION: The re-provisioning is extremely important, because * this allows dynamic replacement of placeholders by using the * XML file as a template that will reinterpreted with the PHP * interpreter! */ $provisionNode->reprovision($provisionFile); // execute the provisioning workflow $this->executeProvision($application, $provisionNode, new \SplFileInfo($webappPath)); } catch (ConfigurationException $ce) { // load the logger and log the XML validation errors $systemLogger = $this->getInitialContext()->getSystemLogger(); $systemLogger->error($ce->__toString()); // additionally log a message that DS will be missing $systemLogger->critical(sprintf('Will skip reading provisioning steps in %s, provisioning might not have been done.', $provisionFile)); } } } }
/** * Parses the bean context's deployment descriptor file for beans * that has to be registered in the object manager. * * @return void */ public function parse() { // load the web application base directory $webappPath = $this->getBeanContext()->getWebappPath(); // prepare the deployment descriptor $deploymentDescriptor = AppEnvironmentHelper::getEnvironmentAwareGlobPattern($webappPath, 'META-INF' . DIRECTORY_SEPARATOR . 'epb'); // query whether we found epb.xml deployment descriptor file if (file_exists($deploymentDescriptor) === false) { return; } // validate the passed configuration file /** @var \AppserverIo\Appserver\Core\Api\ConfigurationService $configurationService */ $configurationService = $this->getApplication()->newService('AppserverIo\\Appserver\\Core\\Api\\ConfigurationService'); $configurationService->validateFile($deploymentDescriptor, null, true); // prepare and initialize the configuration node $epbNode = new EpbNode(); $epbNode->initFromFile($deploymentDescriptor); // query whether or not the deployment descriptor contains any beans /** @var \AppserverIo\Appserver\Core\Api\Node\EnterpriseBeansNode $enterpriseBeans */ if ($enterpriseBeans = $epbNode->getEnterpriseBeans()) { // parse the session beans of the deployment descriptor /** @var \AppserverIo\Appserver\Core\Api\Node\SessionNode $sessionNode */ foreach ($enterpriseBeans->getSessions() as $sessionNode) { $this->processConfigurationNode($sessionNode); } // parse the message driven beans from the deployment descriptor /** @var \AppserverIo\Appserver\Core\Api\Node\MessageDrivenNode $messageDrivenNode */ foreach ($enterpriseBeans->getMessageDrivens() as $messageDrivenNode) { $this->processConfigurationNode($messageDrivenNode); } } }
/** * Returns all datasource files we potentially use * * @return array */ protected function getDatasourceFiles() { // if we have a valid app base we will collect all datasources $datasourceFiles = array(); if (is_dir($appBase = $this->getAppBase())) { // get all the global datasource files first $datasourceFiles = array_merge($datasourceFiles, $this->prepareDatasourceFiles($this->getDeploymentService()->globDir($appBase . DIRECTORY_SEPARATOR . '*-ds.xml', 0, false))); // iterate over all applications and collect the environment specific datasources foreach (glob($appBase . '/*', GLOB_ONLYDIR) as $webappPath) { // append the datasource files of the webapp $datasourceFiles = array_merge($datasourceFiles, $this->prepareDatasourceFiles($this->getDeploymentService()->globDir(AppEnvironmentHelper::getEnvironmentAwareGlobPattern($webappPath, '*-ds')))); } } // return the found datasource files return $datasourceFiles; }
/** * Loads the container instances from the META-INF/containers.xml configuration file of the * passed web application path and add/merge them to/with the system configuration. * * @param \AppserverIo\Appserver\Core\Api\Node\ContainerNodeInterface $containerNode The container node used for property replacement * @param \AppserverIo\Appserver\Core\Interfaces\SystemConfigurationInterface $systemConfiguration The system configuration to add/merge the found containers to/with * @param string $webappPath The path to the web application to search for a META-INF/containers.xml file * * @return void */ public function loadContainerInstance(ContainerNodeInterface $containerNode, SystemConfigurationInterface $systemConfiguration, $webappPath) { // load the service to validate the files /** @var \AppserverIo\Appserver\Core\Api\ConfigurationService $configurationService */ $configurationService = $this->newService('AppserverIo\\Appserver\\Core\\Api\\ConfigurationService'); // iterate through all server configurations (servers.xml), validate and merge them foreach ($this->globDir(AppEnvironmentHelper::getEnvironmentAwareGlobPattern($webappPath, 'META-INF/containers')) as $containersConfigurationFile) { try { // validate the application specific container configurations $configurationService->validateFile($containersConfigurationFile, null); // create a new containers node instance $containersNodeInstance = new ContainersNode(); $containersNodeInstance->initFromFile($containersConfigurationFile); // load the system properties $properties = $this->getSystemProperties($containerNode); // prepare the sytsem properties $this->prepareSystemProperties($properties, $webappPath); /** @var \AppserverIo\Appserver\Core\Api\Node\ContainerNodeInterface $containerNodeInstance */ foreach ($containersNodeInstance->getContainers() as $containerNodeInstance) { // replace the properties for the found container node instance $containerNodeInstance->replaceProperties($properties); // query whether we've to merge or append the server node instance if ($container = $systemConfiguration->getContainer($containerNodeInstance->getName())) { $container->merge($containerNodeInstance); } else { $systemConfiguration->attachContainer($containerNodeInstance); } } } catch (ConfigurationException $ce) { // load the logger and log the XML validation errors $systemLogger = $this->getInitialContext()->getSystemLogger(); $systemLogger->error($ce->__toString()); // additionally log a message that server configuration will be missing $systemLogger->critical(sprintf('Will skip app specific server configuration because of invalid file %s', $containersConfigurationFile)); } } }
/** * Registers the entity managers at startup. * * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance * * @return void */ public function registerEntityManagers(ApplicationInterface $application) { // build up META-INF directory var $metaInfDir = $this->getWebappPath() . DIRECTORY_SEPARATOR . 'META-INF'; // check if we've found a valid directory if (is_dir($metaInfDir) === false) { return; } // check META-INF + subdirectories for XML files with MQ definitions /** @var \AppserverIo\Appserver\Core\Api\DeploymentService $service */ $service = $application->newService('AppserverIo\\Appserver\\Core\\Api\\DeploymentService'); $xmlFiles = $service->globDir(AppEnvironmentHelper::getEnvironmentAwareGlobPattern($this->getWebappPath(), 'META-INF' . DIRECTORY_SEPARATOR . 'persistence')); // load the configuration service instance /** @var \AppserverIo\Appserver\Core\Api\ConfigurationService $configurationService */ $configurationService = $application->newService('AppserverIo\\Appserver\\Core\\Api\\ConfigurationService'); // load the container node to initialize the system properties /** @var \AppserverIo\Appserver\Core\Api\Node\ContainerNodeInterface $containerNode */ $containerNode = $application->getContainer()->getContainerNode(); // gather all the deployed web applications foreach ($xmlFiles as $file) { try { // validate the file here, but skip if the validation fails $configurationService->validateFile($file, null, true); // load the system properties $properties = $service->getSystemProperties($containerNode); // append the application specific properties $properties->add(SystemPropertyKeys::WEBAPP, $webappPath = $application->getWebappPath()); $properties->add(SystemPropertyKeys::WEBAPP_NAME, basename($webappPath)); $properties->add(SystemPropertyKeys::WEBAPP_CACHE, $application->getCacheDir()); $properties->add(SystemPropertyKeys::WEBAPP_SESSION, $application->getSessionDir()); // create a new persistence manager node instance and replace the properties $persistenceNode = new PersistenceNode(); $persistenceNode->initFromFile($file); $persistenceNode->replaceProperties($properties); // register the entity managers found in the configuration foreach ($persistenceNode->getPersistenceUnits() as $persistenceUnitNode) { $this->registerEntityManager($application, $persistenceUnitNode); } } catch (InvalidConfigurationException $e) { // try to load the system logger instance /** @var \Psr\Log\LoggerInterface $systemLogger */ if ($systemLogger = $this->getApplication()->getInitialContext()->getSystemLogger()) { $systemLogger->error($e->getMessage()); $systemLogger->critical(sprintf('Persistence configuration file %s is invalid, needed entity managers might be missing.', $file)); } } catch (\Exception $e) { // try to load the system logger instance /** @var \Psr\Log\LoggerInterface $systemLogger */ if ($systemLogger = $this->getApplication()->getInitialContext()->getSystemLogger()) { $systemLogger->error($e->__toString()); } } } }
/** * Initializes the available CRON configurations and returns them. * * @return array The array with the available CRON configurations */ public function findAll() { try { // initialize the array with the CRON instances $cronInstances = array(); // load the service necessary to validate CRON configuration files /** @var \AppserverIo\Appserver\Core\Api\ConfigurationService $configurationService */ $configurationService = $this->newService('AppserverIo\\Appserver\\Core\\Api\\ConfigurationService'); // load the base CRON configuration file $baseCronPath = $this->getConfdDir('cron.xml'); // we will need to test our CRON configuration files $configurationService->validateFile($baseCronPath, null); // validate the base CRON file and load it as default if validation succeeds $cronInstance = new CronNode(); $cronInstance->initFromFile($baseCronPath); // iterate over all jobs to configure the directory where they has to be executed /** @var \AppserverIo\Appserver\Core\Api\Node\JobNodeInterface $jobNode */ foreach ($cronInstance->getJobs() as $job) { // load the execution information $execute = $job->getExecute(); // query whether or not a base directory has been specified if ($execute && $execute->getDirectory() == null) { // set the directory where the cron.xml file located as base directory, if not $execute->setDirectory(dirname($baseCronPath)); } } // add the default CRON configuration $cronInstances[] = $cronInstance; // iterate over the configured containers /** @var \AppserverIo\Appserver\Core\Api\Node\ContainerNodeInterface $containerNode */ foreach ($this->getSystemConfiguration()->getContainers() as $containerNode) { // iterate over all applications and create the CRON configuration foreach (glob($this->getWebappsDir($containerNode) . '/*', GLOB_ONLYDIR) as $webappPath) { // iterate through all CRON configurations (cron.xml), validate and merge them foreach ($this->globDir(AppEnvironmentHelper::getEnvironmentAwareGlobPattern($webappPath, 'META-INF/cron')) as $cronFile) { try { // validate the file, but skip it if validation fails $configurationService->validateFile($cronFile, null); // load the system properties $properties = $this->getSystemProperties($containerNode); // append the application specific properties $properties->add(SystemPropertyKeys::WEBAPP, $webappPath); $properties->add(SystemPropertyKeys::WEBAPP_NAME, basename($webappPath)); // create a new CRON node instance and replace the properties $cronInstance = new CronNode(); $cronInstance->initFromFile($cronFile); $cronInstance->replaceProperties($properties); // append it to the other CRON configurations $cronInstances[] = $cronInstance; } catch (ConfigurationException $ce) { // load the logger and log the XML validation errors $systemLogger = $this->getInitialContext()->getSystemLogger(); $systemLogger->error($ce->__toString()); // additionally log a message that CRON configuration will be missing $systemLogger->critical(sprintf('Will skip app specific CRON configuration %s, configuration might be faulty.', $cronFile)); } } } } } catch (ConfigurationException $ce) { // load the logger and log the XML validation errors $systemLogger = $this->getInitialContext()->getSystemLogger(); $systemLogger->error($ce->__toString()); // additionally log a message that DS will be missing $systemLogger->critical(sprintf('Problems validating base CRON file %s, this might affect app configurations badly.', $baseCronPath)); } // return the array with the CRON instances return $cronInstances; }
/** * Registers aspects written within source files which we might encounter * * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance * * @return void */ public function registerAspectXml(ApplicationInterface $application) { /** @var \AppserverIo\Appserver\Core\Api\ConfigurationService $configurationService */ $configurationService = $application->newService('AppserverIo\\Appserver\\Core\\Api\\ConfigurationService'); // check if we even have a XMl file to read from $xmlPaths = $configurationService->globDir(AppEnvironmentHelper::getEnvironmentAwareGlobPattern($this->getWebappPath(), '{WEB-INF,META-INF,common}' . DIRECTORY_SEPARATOR . self::CONFIG_FILE_GLOB, GLOB_BRACE), GLOB_BRACE); foreach ($xmlPaths as $xmlPath) { // iterate all XML configuration files we found if (is_readable($xmlPath)) { // validate the file here, if it is not valid we can skip further steps try { $configurationService->validateFile($xmlPath, null, true); } catch (InvalidConfigurationException $e) { /** @var \Psr\Log\LoggerInterface $systemLogger */ $systemLogger = $this->getApplication()->getInitialContext()->getSystemLogger(); $systemLogger->error($e->getMessage()); $systemLogger->critical(sprintf('Pointcuts configuration file %s is invalid, AOP functionality might not work as expected.', $xmlPath)); continue; } // load the aop config $config = new \SimpleXMLElement(file_get_contents($xmlPath)); $config->registerXPathNamespace('a', 'http://www.appserver.io/appserver'); // create us an aspect // name of the aspect will be the application name $aspect = new Aspect(); $aspect->setName($xmlPath); // check if we got some pointcuts foreach ($config->xpath('/a:pointcuts/a:pointcut') as $pointcutConfiguration) { // build up the pointcut and add it to the collection $pointcut = new Pointcut(); $pointcut->setAspectName($aspect->getName()); $pointcut->setName((string) $pointcutConfiguration->{'pointcut-name'}); $pointcut->setPointcutExpression(new PointcutExpression((string) $pointcutConfiguration->{'pointcut-pattern'})); $aspect->getPointcuts()->add($pointcut); } // check if we got some advices foreach ($config->xpath('/a:pointcuts/a:advice') as $adviceConfiguration) { // build up the advice and add it to the aspect $advice = new Advice(); $advice->setAspectName((string) $adviceConfiguration->{'advice-aspect'}); $advice->setName($advice->getAspectName() . '->' . (string) $adviceConfiguration->{'advice-name'}); $advice->setCodeHook((string) $adviceConfiguration->{'advice-type'}); $pointcutPointcut = $this->generatePointcutPointcut((array) $adviceConfiguration->{'advice-pointcuts'}->{'pointcut-name'}, $aspect); $advice->getPointcuts()->add($pointcutPointcut); // finally add the advice to our aspect (we will also add it without pointcuts of its own) $aspect->getAdvices()->add($advice); } // if the aspect contains pointcuts or advices it can be used if ($aspect->getPointcuts()->count() > 0 || $aspect->getAdvices()->count() > 0) { $this->getAspectRegister()->set($aspect->getName(), $aspect); } } } }