Author: Tim Wagner (tw@appserver.io)
Author: Johann Zelger (jz@appserver.io)
Inheritance: extends AppserverIo\Description\Api\Node\AbstractNode, use trait AppserverIo\Appserver\Core\Api\Node\ClassLoadersNodeTrait, use trait LoggersNodeTrait, use trait ManagersNodeTrait, use trait AppserverIo\Appserver\Core\Api\Node\ProvisionersNodeTrait, use trait ParamsNodeTrait
 /**
  * Initializes the available application contexts and returns them.
  *
  * @param \AppserverIo\Appserver\Core\Interfaces\ContainerInterface $container The container we want to add the applications to
  *
  * @return array The array with the application contexts
  */
 public function loadContextInstancesByContainer(ContainerInterface $container)
 {
     try {
         // initialize the array for the context instances
         $contextInstances = array();
         // validate the base context file
         /** @var AppserverIo\Appserver\Core\Api\ConfigurationService $configurationService */
         $configurationService = $this->newService('AppserverIo\\Appserver\\Core\\Api\\ConfigurationService');
         $configurationService->validateFile($baseContextPath = $this->getConfdDir('context.xml'), null);
         //load it as default if validation succeeds
         $baseContext = new ContextNode();
         $baseContext->initFromFile($baseContextPath);
     } 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 context file %s, this might affect app configurations badly.', $baseContextPath));
     }
     // iterate over all applications and create the context configuration
     foreach (glob($container->getAppBase() . '/*', GLOB_ONLYDIR) as $webappPath) {
         // prepare the context path
         $contextPath = basename($webappPath);
         // start with a fresh clone of the base context configuration
         $context = clone $baseContext;
         // try to load a context configuration (from appserver.xml) for the context path
         if ($contextToMerge = $container->getContainerNode()->getHost()->getContext($contextPath)) {
             $context->merge($contextToMerge);
         }
         // iterate through all context configurations (context.xml), validate and merge them
         foreach ($this->globDir($webappPath . '/META-INF/context.xml') as $contextFile) {
             try {
                 // validate the application specific context
                 $configurationService->validateFile($contextFile, null);
                 // create a new context node instance
                 $contextInstance = new ContextNode();
                 $contextInstance->initFromFile($contextFile);
                 // merge it into the default configuration
                 $context->merge($contextInstance);
             } 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 app specific context file %s, configuration might be faulty.', $contextFile));
             }
         }
         // set the real context name
         $context->setName($contextPath);
         // attach the context to the context instance
         $contextInstances[$contextPath] = $context;
     }
     // return the array with the context instances
     return $contextInstances;
 }
 /**
  * Initializes the context instance for the passed webapp path.
  *
  * @param \AppserverIo\Appserver\Core\Api\Node\ContainerNodeInterface $containerNode The container to load the context for
  * @param string                                                      $webappPath    The path to the web application
  *
  * @return \AppserverIo\Appserver\Core\Api\Node\ContextNode The initialized context instance
  */
 public function loadContextInstance(ContainerNodeInterface $containerNode, $webappPath)
 {
     // prepare the context path
     $contextPath = basename($webappPath);
     // load the system properties
     $properties = $this->getSystemProperties($containerNode);
     // append the application specific properties
     $properties->add(SystemPropertyKeys::WEBAPP, $webappPath);
     $properties->add(SystemPropertyKeys::WEBAPP_NAME, $contextPath);
     // validate the base context file
     /** @var \AppserverIo\Appserver\Core\Api\ConfigurationService $configurationService */
     $configurationService = $this->newService('AppserverIo\\Appserver\\Core\\Api\\ConfigurationService');
     $configurationService->validateFile($baseContextPath = $this->getConfdDir('context.xml'), null);
     //load it as default if validation succeeds
     $context = new ContextNode();
     $context->initFromFile($baseContextPath);
     $context->replaceProperties($properties);
     // set the context webapp path
     $context->setWebappPath($webappPath);
     // try to load a context configuration (from appserver.xml) for the context path
     if ($contextToMerge = $containerNode->getHost()->getContext($contextPath)) {
         $contextToMerge->replaceProperties($properties);
         $context->merge($contextToMerge);
     }
     // iterate through all context configurations (context.xml), validate and merge them
     foreach ($this->globDir(AppEnvironmentHelper::getEnvironmentAwareGlobPattern($webappPath, 'META-INF/context')) as $contextFile) {
         try {
             // validate the application specific context
             $configurationService->validateFile($contextFile, null);
             // create a new context node instance and replace the properties
             $contextInstance = new ContextNode();
             $contextInstance->initFromFile($contextFile);
             $contextInstance->replaceProperties($properties);
             // merge it into the default configuration
             $context->merge($contextInstance);
         } 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 app specific context file %s, configuration might be faulty.', $contextFile));
         }
     }
     // set the real context name
     $context->setName($contextPath);
     $context->setEnvironmentName(AppEnvironmentHelper::getEnvironmentModifier($webappPath));
     // return the initialized context instance
     return $context;
 }
 /**
  * This method merges the installation steps of the passed provisioning node into the steps of
  * this instance. If a installation node with the same type already exists, the one of this
  * instance will be overwritten.
  *
  * @param \AppserverIo\Appserver\Core\Api\Node\ContextNode $contextNode The node with the installation steps we want to merge
  *
  * @return void
  */
 public function merge(ContextNode $contextNode)
 {
     // merge the application type
     if ($type = $contextNode->getType()) {
         $this->setType($type);
     }
     // merge the application factory class name
     if ($factory = $contextNode->getFactory()) {
         $this->setFactory($factory);
     }
     // merge the application webapp path
     if ($webappPath = $contextNode->getWebappPath()) {
         $this->setWebappPath($webappPath);
     }
     // load the params defined in this context
     $localParams = $this->getParams();
     // merge them with the passed ones
     foreach ($contextNode->getParams() as $paramToMerge) {
         $isMerged = false;
         /** @var \AppserverIo\Appserver\Core\Api\Node\ParamNode $param */
         foreach ($localParams as $key => $param) {
             if ($param->getName() == $paramToMerge->getName()) {
                 $localParams[$key] = $paramToMerge;
                 $isMerged = true;
             }
         }
         if ($isMerged === false) {
             $localParams[$paramToMerge->getUuid()] = $paramToMerge;
         }
     }
     // set the params back to the context
     $this->setParams($localParams);
     // load the managers defined of this context
     $localManagers = $this->getManagers();
     // merge them with the passed ones
     /**  @var \AppserverIo\Appserver\Core\Api\Node\ManagerNode $managerToMerge */
     foreach ($contextNode->getManagers() as $managerToMerge) {
         $isMerged = false;
         /** @var \AppserverIo\Appserver\Core\Api\Node\ManagerNode $manager */
         foreach ($localManagers as $key => $manager) {
             if ($manager->getName() === $managerToMerge->getName()) {
                 $manager->merge($managerToMerge);
                 $localManagers[$key] = $manager;
                 $isMerged = true;
             }
         }
         if ($isMerged === false) {
             $localManagers[$managerToMerge->getUuid()] = $managerToMerge;
         }
     }
     // set the managers back to the context
     $this->setManagers($localManagers);
     // load the class loaders of this context
     $localClassLoaders = $this->getClassLoaders();
     // merge them with the passed ones
     /** @var \AppserverIo\Appserver\Core\Api\Node\ClassLoaderNode $classLoaderToMerge */
     foreach ($contextNode->getClassLoaders() as $classLoaderToMerge) {
         $isMerged = false;
         /** @var \AppserverIo\Appserver\Core\Api\Node\ClassLoaderNode $classLoader */
         foreach ($localClassLoaders as $key => $classLoader) {
             if ($classLoader->getName() === $classLoaderToMerge->getName()) {
                 $localClassLoaders[$key] = $classLoaderToMerge;
                 $isMerged = true;
             }
         }
         if ($isMerged === false) {
             $localClassLoaders[$classLoaderToMerge->getUuid()] = $classLoaderToMerge;
         }
     }
     // set the class loaders back to the context
     $this->setClassLoaders($localClassLoaders);
     // load the loggers of this context
     $localLoggers = $this->getLoggers();
     // merge them with the passed ones (DO override already registered loggers)
     /** @var \AppserverIo\Appserver\Core\Api\Node\LoggerNode $loggerToMerge */
     foreach ($contextNode->getLoggers() as $loggerToMerge) {
         $localLoggers[$loggerToMerge->getName()] = $loggerToMerge;
     }
     // set the loggers back to the context
     $this->setLoggers($localLoggers);
 }
 /**
  * Prepares the application with the specific data found in the
  * passed context node.
  *
  * @param \AppserverIo\Appserver\Core\Interfaces\ContainerInterface $container The container instance bind the application to
  * @param \AppserverIo\Appserver\Core\Api\Node\ContextNode          $context   The application configuration
  *
  * @return void
  */
 public function prepare(ContainerInterface $container, ContextNode $context)
 {
     // load the unique application name + the naming directory
     $uniqueName = $this->getUniqueName();
     $namingDirectory = $this->getNamingDirectory();
     // create subdirectories for the application and the logger
     $namingDirectory->createSubdirectory(sprintf('php:global/%s', $uniqueName));
     $namingDirectory->createSubdirectory(sprintf('php:global/log/%s', $uniqueName));
     // create the applications 'env' + 'env/persistence' directory the beans + persistence units will be bound to
     $namingDirectory->createSubdirectory(sprintf('php:env/%s', $uniqueName));
     $namingDirectory->createSubdirectory(sprintf('php:global/%s/env', $uniqueName));
     $namingDirectory->createSubdirectory(sprintf('php:global/%s/env/persistence', $uniqueName));
     // bind the directory containing the applications
     $namingDirectory->bind(sprintf('php:env/%s/appBase', $uniqueName), $container->getAppBase());
     // prepare the application specific directories
     $webappPath = sprintf('%s/%s', $this->getAppBase(), $this->getName());
     $tmpDirectory = sprintf('%s/%s', $container->getTmpDir(), $this->getName());
     $cacheDirectory = sprintf('%s/%s', $tmpDirectory, ltrim($context->getParam(DirectoryKeys::CACHE), '/'));
     $sessionDirectory = sprintf('%s/%s', $tmpDirectory, ltrim($context->getParam(DirectoryKeys::SESSION), '/'));
     // prepare the application specific environment variables
     $namingDirectory->bind(sprintf('php:env/%s/webappPath', $uniqueName), $webappPath);
     $namingDirectory->bind(sprintf('php:env/%s/tmpDirectory', $uniqueName), $tmpDirectory);
     $namingDirectory->bind(sprintf('php:env/%s/cacheDirectory', $uniqueName), $cacheDirectory);
     $namingDirectory->bind(sprintf('php:env/%s/sessionDirectory', $uniqueName), $sessionDirectory);
     // bind the interface as reference to the application
     $namingDirectory->bind(sprintf('php:global/%s/env/ApplicationInterface', $uniqueName), $this);
 }
 /**
  * Prepares the application with the specific data found in the
  * passed context node.
  *
  * @param \AppserverIo\Appserver\Core\Api\Node\ContextNode $context The application configuration
  *
  * @return void
  */
 public function prepare(ContextNode $context)
 {
     // load application name + naming directory
     $applicationName = $context->getName();
     $namingDirectory = $this->getNamingDirectory();
     // bind the application (which is also a naming directory)
     $namingDirectory->createSubdirectory(sprintf('php:global/%s', $applicationName));
     // create the applications 'env' + 'env/persistence' directory the beans + persistence units will be bound to
     $namingDirectory->createSubdirectory(sprintf('php:global/%s/env', $this->getName()));
     $namingDirectory->createSubdirectory(sprintf('php:global/%s/env/persistence', $this->getName()));
     // prepare the application specific directories
     $webappPath = sprintf('%s/%s', $namingDirectory->search('php:env/appBase'), $applicationName);
     $tmpDirectory = sprintf('%s/%s', $namingDirectory->search('php:env/tmpDirectory'), $applicationName);
     $cacheDirectory = sprintf('%s/%s', $tmpDirectory, ltrim($context->getParam(DirectoryKeys::CACHE), '/'));
     $sessionDirectory = sprintf('%s/%s', $tmpDirectory, ltrim($context->getParam(DirectoryKeys::SESSION), '/'));
     // prepare the application specific environment variables
     $namingDirectory->createSubdirectory(sprintf('php:env/%s', $applicationName));
     $namingDirectory->bind(sprintf('php:env/%s/webappPath', $applicationName), $webappPath);
     $namingDirectory->bind(sprintf('php:env/%s/tmpDirectory', $applicationName), $tmpDirectory);
     $namingDirectory->bind(sprintf('php:env/%s/cacheDirectory', $applicationName), $cacheDirectory);
     $namingDirectory->bind(sprintf('php:env/%s/sessionDirectory', $applicationName), $sessionDirectory);
     // bind the interface as reference to the application
     $namingDirectory->bind(sprintf('php:global/%s/env/ApplicationInterface', $this->getName()), $this);
 }
 /**
  * Visitor method that registers the application in the container.
  *
  * @param \AppserverIo\Appserver\Core\Interfaces\ContainerInterface $container The container instance bind the application to
  * @param \AppserverIo\Appserver\Core\Api\Node\ContextNode          $context   The application configuration
  *
  * @return void
  */
 public static function visit(ContainerInterface $container, ContextNode $context)
 {
     // prepare the path to the applications base directory
     $folder = $container->getAppBase() . DIRECTORY_SEPARATOR . $context->getName();
     // declare META-INF and WEB-INF directory
     $webInfDir = $folder . DIRECTORY_SEPARATOR . 'WEB-INF';
     $metaInfDir = $folder . DIRECTORY_SEPARATOR . 'META-INF';
     // check if we've a directory containing a valid application,
     // at least a WEB-INF or META-INF folder has to be available
     if (!is_dir($webInfDir) && !is_dir($metaInfDir)) {
         return;
     }
     // load the naming directory + initial context
     $initialContext = $container->getInitialContext();
     $namingDirectory = $container->getNamingDirectory();
     // load the application service
     $appService = $container->newService('AppserverIo\\Appserver\\Core\\Api\\AppService');
     // load the application type
     $contextType = $context->getType();
     $applicationName = $context->getName();
     // create a new application instance
     /** @var \AppserverIo\Appserver\Application\Application $application */
     $application = new $contextType();
     // initialize the storage for managers, virtual hosts an class loaders
     $managers = new GenericStackable();
     $provisioners = new GenericStackable();
     $classLoaders = new GenericStackable();
     // initialize the generic instances and information
     $application->injectManagers($managers);
     $application->injectName($applicationName);
     $application->injectProvisioners($provisioners);
     $application->injectClassLoaders($classLoaders);
     $application->injectInitialContext($initialContext);
     $application->injectNamingDirectory($namingDirectory);
     // prepare the application instance
     $application->prepare($context);
     // create the applications temporary folders and cleans the folders up
     /** @var \AppserverIo\Appserver\Core\Api\AppService $appService */
     PermissionHelper::sudo(array($appService, 'createTmpFolders'), array($application));
     $appService->cleanUpFolders($application);
     // add the configured class loaders
     /** @var \AppserverIo\Appserver\Core\Api\Node\ClassLoaderNode $classLoader */
     foreach ($context->getClassLoaders() as $classLoader) {
         /** @var \AppserverIo\Appserver\Core\Interfaces\ClassLoaderFactoryInterface $classLoaderFactory */
         if ($classLoaderFactory = $classLoader->getFactory()) {
             // use the factory if available
             $classLoaderFactory::visit($application, $classLoader);
         } else {
             // if not, try to instanciate the class loader directly
             $classLoaderType = $classLoader->getType();
             $application->addClassLoader(new $classLoaderType($classLoader), $classLoader);
         }
     }
     // add the configured managers
     /** @var \AppserverIo\Appserver\Core\Api\Node\ManagerNode $manager */
     foreach ($context->getManagers() as $manager) {
         if ($managerFactory = $manager->getFactory()) {
             // use the factory if available
             $managerFactory::visit($application, $manager);
         } else {
             // if not, try to instanciate the manager directly
             $managerType = $manager->getType();
             $application->addManager(new $managerType($manager), $manager);
         }
     }
     // add the configured provisioners
     /** @var \AppserverIo\Appserver\Core\Api\Node\ProvisionerNode $provisioner */
     foreach ($context->getProvisioners() as $provisioner) {
         if ($provisionerFactory = $provisioner->getFactory()) {
             // use the factory if available
             $provisionerFactory::visit($application, $provisioner);
         } else {
             // if not, try to instanciate the provisioner directly
             $provisionerType = $provisioner->getType();
             $application->addProvisioner(new $provisionerType($provisioner), $provisioner);
         }
     }
     // add the application to the container
     $container->addApplication($application);
 }