text:
<?php

namespace Symbiote\FrontendObjects\Page;

use Page;

use Object;

use Symbiote\MultiValueField\Fields\MultiValueTextField;

use SilverStripe\Core\Extensible;

use Symbiote\FrontendObjects\Extension\FrontendCreateableExtension;

use SilverStripe\Assets\File;
use Symbiote\AdvancedWorkflow\DataObjects\WorkflowDefinition;
use SilverStripe\Assets\Folder;
use Symbiote\FrontendObjects\Page\FrontendCreateableObject;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\CheckboxField;
use SilverStripe\Forms\HTMLEditor\HTMLEditorField;
use SilverStripe\ORM\Hierarchy\Hierarchy;
use SilverStripe\Forms\TreeDropdownField;
use SilverStripe\Forms\TreeMultiselectField;
use Symbiote\AdvancedWorkflow\Extensions\WorkflowApplicable;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\TextField;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\ORM\DataList;
use SilverStripe\Security\Member;
use Symbiote\AdvancedWorkflow\DataObjects\WorkflowInstance;
use SilverStripe\ORM\ArrayList;
use Symbiote\AdvancedWorkflow\Controllers\FrontEndWorkflowController;
use SilverStripe\Security\Permission;
use SilverStripe\Versioned\Versioned;
use SilverStripe\ORM\DataObject;
use SilverStripe\Control\Director;
use SilverStripe\i18n\i18n;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\HiddenField;
use SilverStripe\Core\Config\Config;
use SilverStripe\Forms\FormAction;
use SilverStripe\Forms\Form;
use Symbiote\FrontendObjects\Control\ObjectCreatorPage_FrontEndWorkflowController;
use SilverStripe\ORM\ValidationException;
use Symbiote\AdvancedWorkflow\Services\WorkflowService;
use SilverStripe\Control\Controller;
use PageController;
use Symbiote\MultiValueField\Fields\KeyValueField;
use Symbiote\MultiValueField\Fields\MultiValueDropdownField;

/**
 * A page type that lets users create other data objects from the frontend of
 * their website.
 *
 * @author marcus@silverstripe.com.au
 * @license BSD License http://silverstripe.org/bsd-license/
 */
class ObjectCreatorPage extends Page {
    private static $table_name = 'ObjectCreatorPage';

	private static $createable_types = array('Page', File::class);
	private static $db = array(
        'CreateType' => 'Varchar(255)',
        'CreateTypeOptions' => 'MultiValueField',
		'CreateLocationID' => 'Int',
		'RestrictCreationTo' => 'Varchar(255)',
        'AllowUserSelection' => 'Boolean',
		'CreateButtonText' => 'Varchar',
		'PublishOnCreate' => 'Boolean',
		'ShowCmsLink' => 'Boolean',
		'WhenObjectExists' => "Enum('Rename, Replace, Error', 'Rename')",
		'AllowUserWhenObjectExists' => 'Boolean',
		'SuccessMessage' => 'HTMLText',
		'EditingSuccessMessage' => 'HTMLText',
		'AllowEditing' => 'Boolean',
		'AdditionalProperties'		=> 'MultiValueField',
		'ReviewWithPageTemplate'	=> 'Boolean',
	);
	private static $has_one = array(
		'WorkflowDefinition' => WorkflowDefinition::class
	);
	private static $defaults = array(
		'CreateButtonText' => 'Create',
		'PublishOnCreate' => true
	);

	private static $icon = 'frontend-objects/images/objectcreatorpage.png';

	/**
	 * A mapping between object create type and the type of parent
	 * that it should be created under (if applicable)
	 *
	 * @var array
	 */
	private static $parent_map = array(
		'File' => Folder::class
	);

    public function allSubtypes($type) {
        $classes = ClassInfo::getValidSubClasses($type);

        $baseClassIndex = array_search(self::class, $classes);
        if ($baseClassIndex !== false) {
            unset($classes[$baseClassIndex]);
        }

        $currentClass = null;

        $result = [];
        foreach ($classes as $class) {
            $instance = singleton($class);
            if (!$instance->canCreate()) {
                continue;
            }
            if ($perms = $instance->config()->get('need_permission')) {
                if (!$this->can($perms)) {
                    continue;
                }
            }

            $pageTypeName = $instance->i18n_singular_name();

            $currentClass = $class;
            $result[$class] = $pageTypeName;

            // If we're in translation mode, the link between the translated pagetype title and the actual classname
            // might not be obvious, so we add it in parantheses. Example: class "RedirectorPage" has the title
            // "Weiterleitung" in German, so it shows up as "Weiterleitung (RedirectorPage)"
            if (i18n::getData()->langFromLocale(i18n::get_locale()) != 'en') {
                $result[$class] = $result[$class] .  " ({$class})";
            }
        }

        return $result;
    }

    public function allAvailableTypes() {
        $types = ClassInfo::implementorsOf(FrontendCreateableObject::class);

		if (!$types) {
			$types = array();
		}

		$types = array_merge($types, $this->config()->createable_types);
        $types = array_combine($types, $types);

        $allTypes = [];
        foreach ($types as $type => $typeLabel) {
            $typeResult = $this->allSubtypes($type);
            $allTypes = array_merge($allTypes, $typeResult);
        }

        return $allTypes;
    }

	public function getCMSFields() {
		$fields = parent::getCMSFields();

		$types = ClassInfo::implementorsOf(FrontendCreateableObject::class);

		if (!$types) {
			$types = array();
		}

		$types = array_merge($types, $this->config()->createable_types);
        $types = array_combine($types, $types);

        $allTypes = $this->allAvailableTypes();

        $fields->addFieldToTab('Root.Main', new DropdownField('CreateType', _t('FrontendCreate.CREATE_TYPE', 'Create objects of which type?'), $types), 'Content');
        $fields->addFieldToTab('Root.Main', MultiValueDropdownField::create('CreateTypeOptions', _t('FrontendCreate.CREATE_TYPE', 'Allow user to select type (type selected above becomes the default)'), $allTypes), 'Content');
		$fields->addFieldToTab('Root.Main', new CheckboxField('PublishOnCreate', _t('FrontendCreate.PUBLISH_ON_CREATE', 'Publish after creating (if applicable)')), 'Content');
		$fields->addFieldToTab('Root.Main', new CheckboxField('ShowCmsLink', _t('FrontendCreate.SHOW_CMS_LINK', 'Show CMS link for Page objects after creation')), 'Content');
		$fields->addFieldToTab('Root.Main', new CheckboxField('AllowEditing', _t('FrontendCreate.ALLOW_EDITING', 'Allow frontend editing of this page after creation')), 'Content');
		$fields->addFieldToTab('Root.AfterSubmission', HTMLEditorField::create('SuccessMessage', 'Success Message displayed after new object creation')->setRightTitle('Use $Link, $EditLink and $Title to reference the created page'));
		$fields->addFieldToTab('Root.AfterSubmission', HTMLEditorField::create('EditingSuccessMessage', 'Success Message dislpayed after editing existing object')->setRightTitle('Use $Link, $EditLink and $Title to reference the created page'));

		if ($this->CreateType) {
			if (Extensible::has_extension($this->CreateType, Hierarchy::class)) {
				$parentType = $this->ParentMap();

				if (!$this->AllowUserSelection) {
					$fields->addFieldToTab('Root.Main', new TreeDropdownField('CreateLocationID', _t('FrontendCreate.CREATE_LOCATION', 'Create new items where?'), $parentType), 'Content');
					$fields->addFieldToTab('Root.Main', new CheckboxField('AllowUserSelection', _t('FrontendCreate.ALLOW_USER_SELECT', 'Allow users to select where to create items')), 'Content');
				} else {
					$fields->addFieldToTab('Root.Main', new CheckboxField('AllowUserSelection', _t('FrontendCreate.ALLOW_USER_SELECT', 'Allow users to select where to create items')), 'Content');
					$fields->addFieldToTab('Root.Main', $ts = TreeMultiselectField::create('RestrictCreationToItems', _t('FrontendCreate.RESTRICT_LOCATION', 'Restrict creation to beneath this location'), $parentType), 'Content');
					$ts->setValue($this->RestrictCreationTo);
				}
			}
			if (Extensible::has_extension($this->CreateType, WorkflowApplicable::class)) {
				$workflows = WorkflowDefinition::get()->map()->toArray();
                $fields->addFieldToTab(
                    'Root.Main',
                    DropdownField::create('WorkflowDefinitionID', 'Workflow Definition', $workflows)
                        ->setHasEmptyDefault(true)->setRightTitle("Do not use if page is created in a location with workflow"),
                    'Content'
                );
				// $fields->addFieldToTab('Root.Main', CheckboxField::create('ReviewWithPageTemplate', 'Make Workflow review page render with page template?')
				// 		->setDescription('Renders the page with its controller and shows how it would appear when published. $Form or $CreateForm must exist in the template for the review fields and save buttons.'), 'Content');
			}
		} else {
			$fields->addFieldToTab('Root.Main', new LiteralField('SaveNotice', _t('FrontendCreate.SAVE_NOTICE', '
Select a type to create and save the page for additional options
')), 'Content');
		}

		$fields->addFieldToTab('Root.Main', KeyValueField::create('AdditionalProperties', 'Extra properties to set on created items'), 'Content');

		$fields->addFieldToTab('Root.Main', new TextField('CreateButtonText', _t('FrontendCreate.UPLOAD_TEXT', 'Upload button text')), 'Content');

		if ($this->useObjectExistsHandling()) {
			$fields->addFieldToTab('Root.Main', new DropdownField('WhenObjectExists', 'When Object Exists', $this->dbObject('WhenObjectExists')->EnumValues()), 'Content');
			$fields->addFieldToTab('Root.Main', new CheckboxField('AllowUserWhenObjectExists', _t('FrontendCreate.ALLOW_USER_WHEN_OBJECT_EXISTS', 'Allow users to select an action to take if the object already exists')), 'Content');
		}

		$this->extend('updateObjectCreatorPageCMSFields', $fields);

		return $fields;
	}

	public function onBeforeWrite() {
		parent::onBeforeWrite();

		if (isset($_REQUEST['ClearCreateLocation'])) {
			$this->CreateLocationID = 0;
		}
	}

	public function onChangeRestrictCreationToItems($items) {
		$this->RestrictCreationTo = implode(',', $items);
		return false;
	}

	public function ParentMap() {
		$parentMap = $this->config()->parent_map;
		if (isset($parentMap[$this->CreateType])) {
			$parentType = $parentMap[$this->CreateType];
		} else {
			$parentType = $this->CreateType;
			$baseClass = ClassInfo::baseDataClass($parentType);
			if ($baseClass && $baseClass === SiteTree::class) {
				$parentType = SiteTree::class;
			}
		}
		return $parentType;
	}

	public function RestrictCreationToItems() {
		$parentType = $this->ParentMap();

		$items = explode(',', $this->RestrictCreationTo);
		$list = DataList::create($parentType)->filter('ID', $items);
		return $list;
	}

	/**
	 * Return link for the review listing page
	 */
	public function LinkReview() {
		if (!$this->canReview(Member::currentUser(), null))
		{
			return '';
		}
		return $this->Link('review');
	}

	/**
	 * Returns all viewable and editable items that are waiting
	 * to be approved.
	 *
	 * @return ArrayList
	 */
	protected $_cache_review_items = null;
	public function ReviewItems() {
		if ($this->_cache_review_items) {
			return $this->_cache_review_items;
		}
		$workflowDef = $this->WorkflowDefinition();
		$member = Member::currentUser();
		if (!$member || !$workflowDef || !$workflowDef->exists()) {
			return;
		}

		if (!$this->canReview($member, null))
		{
			return;
		}

		$workflowInstances = WorkflowInstance::get()->filter(array(
			'DefinitionID' => $this->WorkflowDefinitionID,
			'WorkflowStatus:not' => 'Complete',
		))->sort('LastEdited', 'DESC');

		$result = array();
		foreach ($workflowInstances as $workflowInstance)
		{
			$page = $workflowInstance->Target();
			if (!$page || !$page->exists())
			{
				continue;
			}
			$canEdit = $page->canEdit();
			$canView = $workflowInstance->canView();

			if ($canView || $canEdit)
			{
				$page->_canView = $canView;
				$page->_canEdit = $canEdit;

				// Added CurrentActionSort so that reviewable items are sorted from most approved to least approved.
				$page->_CurrentActionSort = 0;
				$workflowCurrentAction = $workflowInstance->CurrentAction();
				if ($workflowCurrentAction
					&& ($workflowBaseAction = $workflowCurrentAction->BaseAction()))
				{
					$page->_CurrentActionSort = $workflowInstance->CurrentAction()->BaseAction()->Sort;
				}

				if ($canEdit)
				{
					// In the case that the 'FrontendCreateableExtension' isn't applied, setup the
					// review/edit links automatically based on this context.
					if (!$page->FrontendReviewLink) {
						$page->FrontendReviewLink = $this->Link('review/'.$page->ID);
					}
					if ($this->data()->AllowEditing && !$page->FrontendEditLink)
					{
						$page->FrontendEditLink = $this->Link('edit/'.$page->ID);
					}
				}
				$page->WorkflowInstance = $workflowInstance; // Explicitly access workflow instance on templates
				$page->failover = $workflowInstance; // Fallback to Workflow data in templates
				$result[] = $page;
			}
		}
		$result = new ArrayList($result);
		return $this->_cache_review_items = $result;
	}

	/**
	 * Items the user may have previously reviewed but are no longer editable by them.
	 *
	 * @return ArrayList
	 */
	public function ReviewItemsViewable() {
		$reviewItems = $this->ReviewItems();
		if (!$reviewItems) {
			return;
		}
		$result = array();
		foreach ($reviewItems as $page)
		{
			if ($page && $page->_canView && !$page->_canEdit)
			{
				$result[] = $page;
			}
		}
		return new ArrayList($result);
	}

	/**
	 * Items the user the user can review and approve
	 *
	 * @return ArrayList
	 */
	public function ReviewItemsEditable() {
		$reviewItems = $this->ReviewItems();
		if (!$reviewItems) {
			return;
		}
		$result = array();
		foreach ($reviewItems as $page)
		{
			if ($page && $page->_canEdit)
			{
				$result[] = $page;
			}
		}
		$result = new ArrayList($result);
		$result = $result->sort(array(
			'_CurrentActionSort' => 'DESC',
		));
		return $result;
	}

	/**
	 * checks to see if the object being created has the objectExists() method
	 * which is needed to check for existing object
	 * @return bool
	 * */
	public function useObjectExistsHandling() {
		if ($this->CreateType) {
			return singleton($this->CreateType)->hasMethod('objectExists');
		}
	}

	/**
	 * Check whether the member can review submissions or not
	 *
	 * @param Member $member
	 * @param Record $record Check if the user canReview() the record, if 'null' is supplied, check if user
	 *						 can see the review listing page.
	 * @return bool|null
	 */
	public function canReview($member, $record) {
		$extended = $this->extendedCan(__FUNCTION__, $member);
		if($extended !== null) return $extended;

		if (!class_exists(FrontEndWorkflowController::class)) {
			// Cannot review if there's no workflow module installed
			return false;
		}

		// NOTE(Jake): Might *want* to update the below logic so that when "$record === null"
		//			   the user must belong in the Restricted User/Group.
		if (!$this->WorkflowDefinitionID) {
			// Cannot review if there's no workflow applied to the object creator page.
			return false;
		}

		if ($record && !$record->getWorkflowInstance()) {
			// Cannot review if there's no workflow active on the record.
			return false;
		}

		if (!$member) {
			// Cannot review if not a logged in member.
			return false;
		}

		if (Permission::check('ADMIN', 'any', $member)) {
			return true;
		}

		if ($record) {
			$extended = $record->canEdit($member);
			if($extended !== null) return $extended;
		}
		return true;
	}
}


text:
package org.apache.geronimo.gbean.runtime;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.management.ObjectName;

import org.apache.geronimo.gbean.ServiceInterfaces;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.geronimo.gbean.AbstractName;
import org.apache.geronimo.gbean.AbstractNameQuery;
import org.apache.geronimo.gbean.GAttributeInfo;
import org.apache.geronimo.gbean.GBeanData;
import org.apache.geronimo.gbean.GBeanInfo;
import org.apache.geronimo.gbean.GBeanLifecycle;
import org.apache.geronimo.gbean.GConstructorInfo;
import org.apache.geronimo.gbean.GOperationInfo;
import org.apache.geronimo.gbean.GOperationSignature;
import org.apache.geronimo.gbean.GReferenceInfo;
import org.apache.geronimo.gbean.InvalidConfigurationException;
import org.apache.geronimo.gbean.ReferencePatterns;
import org.apache.geronimo.kernel.DependencyManager;
import org.apache.geronimo.kernel.GBeanNotFoundException;
import org.apache.geronimo.kernel.Kernel;
import org.apache.geronimo.kernel.NoSuchAttributeException;
import org.apache.geronimo.kernel.NoSuchOperationException;
import org.apache.xbean.osgi.bundle.util.BundleClassLoader;
import org.apache.xbean.osgi.bundle.util.equinox.EquinoxBundleClassLoader;
import org.apache.geronimo.kernel.config.ManageableAttributeStore;
import org.apache.geronimo.kernel.management.State;
import org.apache.geronimo.kernel.management.StateManageable;
import org.apache.geronimo.kernel.osgi.FrameworkUtils;
import org.apache.geronimo.kernel.repository.Artifact;
import org.apache.xbean.recipe.ConstructionException;
import org.apache.xbean.recipe.ObjectRecipe;
import org.apache.xbean.recipe.Option;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;

/**
 * A GBeanInstance is a J2EE Management Managed Object, and is standard base for Geronimo services.
 *
 * @version $Rev:385718 $ $Date$
 */
public final class GBeanInstance implements StateManageable {
    private static final Logger log = LoggerFactory.getLogger(GBeanInstance.class);

    private static final int MAX_DEPENDENCY_STATE_REASON_NUM = Integer.getInteger("org.apache.geronimo.gbean.runtime.max_state_reason_count", 5);

    private static final String ABSTRACT_NAME_PROPERTY = "org.apache.geronimo.abstractName";
    private static final String OSGI_JNDI_NAME_PROPERTY = "osgi.jndi.service.name";

    private static final int DESTROYED = 0;
    private static final int CREATING = 1;
    private static final int RUNNING = 2;
    private static final int DESTROYING = 3;

    /**
     * Attribute name used to retrieve the RawInvoker for the GBean
     */
    public static final String RAW_INVOKER = "$$RAW_INVOKER$$";

    /**
     * The kernel in which this server is registered.
     */
    private final Kernel kernel;

    /**
     * The ManageableAttributeStore notified of any changes to manageable
     * attributes.  This is lazy-loaded as manageable attributes are set.
     */
    private ManageableAttributeStore manageableStore;

    /**
     * the abstract name of this service
     */
    private final AbstractName abstractName;

    /**
     * This handles all state transiitions for this instance.
     */
    private final GBeanInstanceState gbeanInstanceState;

    /**
     * The objectRecipe used to create the instance
     */
    private final ObjectRecipe objectRecipe;

    /**
     * A fast index based raw invoker for this GBean.
     */
    private final RawInvoker rawInvoker;

    /**
     * The single listener to which we broadcast lifecycle change events.
     */
    private final LifecycleBroadcaster lifecycleBroadcaster;

    /**
     * Interfaces for this GBean
     */
    private final String[] interfaces;

    /**
     * Attributes lookup table
     */
    private final GBeanAttribute[] attributes;

    /**
     * Attributes supported by this GBeanMBean by (String) name.
     */
    private final Map<String, Integer> attributeIndex = new HashMap<String, Integer>();

    /**
     * References lookup table
     */
    private final GBeanReference[] references;

    /**
     * References supported by this GBeanMBean by (String) name.
     */
    private final Map<String, Integer> referenceIndex = new HashMap<String, Integer>();

    /**
     * Dependencies supported by this GBean.
     */
    private final GBeanDependency[] dependencies;

    /**
     * Operations lookup table
     */
    private final GBeanOperation[] operations;

    /**
     * Operations supported by this GBeanMBean by (GOperationSignature) name.
     */
    private final Map<GOperationSignature, Integer> operationIndex = new HashMap<GOperationSignature, Integer>();

    /**
     * The classloader used for all invocations and creating targets.
     */
    private final ClassLoader classLoader;

    private final BundleContext bundleContext;

    /**
     * Metadata describing the attributes, operations and references of this GBean
     */
    private final GBeanInfo gbeanInfo;

    /**
     * Our name
     */
    private final String name;

    /**
     * Java type of the wrapped GBean class
     */
    private final Class type;

    /**
     * Has this instance been destroyed?
     */
    private boolean dead = false;

    /**
     * The state of the internal gbean instance that we are wrapping.
     */
    private int instanceState = DESTROYED;

    /**
     * Target instance of this GBean wrapper
     */
    private Object target;

    /**
     * The time this application started.
     */
    private long startTime;

    /**
     * This is used to signal the creating thread that it should
     * fail when it returns from usercode.  This is set when a
     * reference has gone offline during construction.
     */
    private boolean shouldFail = false;

    /**
     * Used to track instance
     */
    private InstanceRegistry instanceRegistry;

    private String stateReason;

    private String[] serviceInterfaces;
    private Dictionary serviceProperties;
    private ServiceRegistration serviceRegistration;

    /**
     * Construct a GBeanMBean using the supplied GBeanData and bundle
     *
     * @param gbeanData     the data for the new GBean including GBeanInfo, intial attribute values, and reference patterns
     * @param bundleContext
     * @throws org.apache.geronimo.gbean.InvalidConfigurationException
     *          if the gbeanInfo is inconsistent with the actual java classes, such as
     *          mismatched attribute types or the intial data cannot be set
     */
    public GBeanInstance(GBeanData gbeanData, Kernel kernel, DependencyManager dependencyManager, LifecycleBroadcaster lifecycleBroadcaster, BundleContext bundleContext) throws InvalidConfigurationException {
        this.abstractName = gbeanData.getAbstractName();
        this.kernel = kernel;
        this.lifecycleBroadcaster = lifecycleBroadcaster;
        this.gbeanInstanceState = new GBeanInstanceState(abstractName, kernel, dependencyManager, this, lifecycleBroadcaster);
        this.bundleContext = bundleContext;

        GBeanInfo gbeanInfo = gbeanData.getGBeanInfo();
        try {
            type = bundleContext.getBundle().loadClass(gbeanInfo.getClassName());
        } catch (ClassNotFoundException e) {
            throw new InvalidConfigurationException("Could not load GBeanInfo class from classloader: " + bundleContext +
                    " className=" + gbeanInfo.getClassName(), e);
        }

        if (FrameworkUtils.useURLClassLoader() && FrameworkUtils.isEquinox()) {
            this.classLoader = new EquinoxBundleClassLoader(bundleContext.getBundle());
        } else {
            this.classLoader = new BundleClassLoader(bundleContext.getBundle());
        }

        name = gbeanInfo.getName();

        // interfaces
        interfaces = gbeanInfo.getInterfaces().toArray(new String[gbeanInfo.getInterfaces().size()]);

        // attributes
        attributes = buildAttributes(gbeanInfo);
        for (int i = 0; i < attributes.length; i++) {
            attributeIndex.put(attributes[i].getName(), i);
        }

        // references
        Set<GBeanReference> referencesSet = new HashSet<GBeanReference>();
        Set<GBeanDependency> dependencySet = new HashSet<GBeanDependency>();
        buildReferencesAndDependencies(gbeanData, gbeanInfo, referencesSet, dependencySet);

        references = referencesSet.toArray(new GBeanReference[referencesSet.size()]);
        for (int i = 0; i < references.length; i++) {
            referenceIndex.put(references[i].getName(), i);
        }

        //dependencies
        for (ReferencePatterns referencePatterns : gbeanData.getDependencies()) {
            AbstractName dependencyName = referencePatterns.getAbstractName();
            dependencySet.add(new GBeanDependency(this, dependencyName, kernel));
        }
        dependencies = dependencySet.toArray(new GBeanDependency[dependencySet.size()]);

        // framework operations -- all framework operations have currently been removed

        // operations
        Map<GOperationSignature, GBeanOperation> operationsMap = new HashMap<GOperationSignature, GBeanOperation>();
        for (GOperationInfo operationInfo : gbeanInfo.getOperations()) {
            GOperationSignature signature = new GOperationSignature(operationInfo.getName(), operationInfo.getParameterList());
            // do not allow overriding of framework operations
            if (!operationsMap.containsKey(signature)) {
                GBeanOperation operation = new GBeanOperation(this, operationInfo);
                operationsMap.put(signature, operation);
            }
        }
        operations = new GBeanOperation[operationsMap.size()];
        int opCounter = 0;
        for (Map.Entry<GOperationSignature, GBeanOperation> entry : operationsMap.entrySet()) {
            operations[opCounter] = entry.getValue();
            operationIndex.put(entry.getKey(), opCounter);
            opCounter++;
        }

        // rebuild the gbean info based on the current attributes, operations, and references because
        // the above code add new attributes and operations
        this.gbeanInfo = rebuildGBeanInfo(gbeanInfo.getConstructor(), gbeanInfo.getJ2eeType(), gbeanInfo.getPriority(), gbeanInfo.isOsgiService(), gbeanInfo.getServiceInterfaces());

        objectRecipe = newObjectRecipe(gbeanData);

        // create the raw invokers
        rawInvoker = new RawInvoker(this);

        //Add the reference to all applicable reference collections before possibly starting the gbean having an
        //explicit reference to the reference.
        for (int i = 0; i < references.length; i++) {
            references[i].online();
        }
        for (int i = 0; i < dependencies.length; i++) {
            dependencies[i].online();
        }

        this.serviceInterfaces = gbeanData.getServiceInterfaces();
        this.serviceProperties = gbeanData.getServiceProperties();
    }

    protected ObjectRecipe newObjectRecipe(GBeanData gbeanData) {
        GBeanInfo beanInfo = gbeanData.getGBeanInfo();
        List<String> cstrNames = beanInfo.getConstructor().getAttributeNames();
        Class[] cstrTypes = new Class[cstrNames.size()];
        for (int i = 0; i < cstrTypes.length; i++) {
            String argumentName = cstrNames.get(i);
            if (referenceIndex.containsKey(argumentName)) {
                Integer index = referenceIndex.get(argumentName);
                GBeanReference reference = references[index];
                cstrTypes[i] = reference.getProxyType();
            } else if (attributeIndex.containsKey(argumentName)) {
                Integer index = attributeIndex.get(argumentName);
                GBeanAttribute attribute = attributes[index];
                cstrTypes[i] = attribute.getType();
            }
        }
        ObjectRecipe objectRecipe = new ObjectRecipe(type, cstrNames.toArray(new String[0]), cstrTypes);
        objectRecipe.allow(Option.IGNORE_MISSING_PROPERTIES);

        // set the initial attribute values
        Map<String, Object> dataAttributes = gbeanData.getAttributes();
        for (GAttributeInfo attributeInfo : beanInfo.getAttributes()) {
            Integer integer = attributeIndex.get(attributeInfo.getName());
            GBeanAttribute attribute = attributes[integer];
            String attributeName = attribute.getName();
            if (attribute.isPersistent() || attribute.isDynamic()) {
                Object attributeValue = dataAttributes.get(attributeName);
                if (null != attributeValue) {
                    attribute.setPersistentValue(attributeValue);
                }
                if (attribute.isPersistent() && null != attributeValue && !attribute.isDynamic()) {
                    objectRecipe.setProperty(attributeName, attribute.getPersistentValue());
                }
            } else if (attribute.isSpecial() && (attribute.isWritable() || cstrNames.contains(attributeName))) {
                objectRecipe.setProperty(attributeName, attribute.getPersistentValue());
            }
        }

        return objectRecipe;
    }

    protected void buildReferencesAndDependencies(GBeanData gbeanData,
                                                  GBeanInfo gbeanInfo,
                                                  Set<GBeanReference> referencesSet,
                                                  Set<GBeanDependency> dependencySet) {
        Map<String, ReferencePatterns> dataReferences = gbeanData.getReferences();
        for (GReferenceInfo referenceInfo : gbeanInfo.getReferences()) {
            String referenceName = referenceInfo.getName();
            ReferencePatterns referencePatterns = dataReferences.remove(referenceName);
            if (referenceInfo.getProxyType().equals(Collection.class.getName())) {
                referencesSet.add(new GBeanCollectionReference(this, referenceInfo, kernel, referencePatterns));
            } else {
                referencesSet.add(new GBeanSingleReference(this, referenceInfo, kernel, referencePatterns));
                if (referencePatterns != null) {
                    dependencySet.add(new GBeanDependency(this, referencePatterns.getAbstractName(), kernel));
                }
            }
        }
        if (!dataReferences.isEmpty()) {
            throw new IllegalStateException("Attempting to set unknown references: " + dataReferences.keySet());
        }
    }

    protected GBeanAttribute[] buildAttributes(GBeanInfo gbeanInfo) {
        Map<String, GBeanAttribute> attributesMap = new HashMap<String, GBeanAttribute>();
        for (GAttributeInfo attributeInfo : gbeanInfo.getAttributes()) {
            attributesMap.put(attributeInfo.getName(), new GBeanAttribute(this, attributeInfo));
        }
        addManagedObjectAttributes(attributesMap);

        return attributesMap.values().toArray(new GBeanAttribute[attributesMap.size()]);
    }

    public void die() throws GBeanNotFoundException {
        synchronized (this) {
            if (dead) {
                // someone beat us to the punch... this instance should have never been found in the first place
                throw new GBeanNotFoundException(abstractName);
            }
            dead = true;
        }

        // if the bean is already stopped or failed, this will do nothing; otherwise it will shutdown the bean
        gbeanInstanceState.fail();

        for (int i = 0; i < references.length; i++) {
            references[i].offline();
        }
        for (int i = 0; i < dependencies.length; i++) {
            dependencies[i].offline();
        }

        // tell everyone we are done
        lifecycleBroadcaster.fireUnloadedEvent();

        manageableStore = null;
    }

    public synchronized void setInstanceRegistry(InstanceRegistry instanceRegistry) {
        this.instanceRegistry = instanceRegistry;
    }

    /**
     * Gets the name of the GBean as defined in the gbean info.
     *
     * @return the gbean name
     */
    public String getName() {
        return name;
    }

    /**
     * The bundle used to build this gbean.
     *
     * @return the bundle used to build this gbean
     */
    public Bundle getBundle() {
        return bundleContext.getBundle();
    }

    /**
     * Has this gbean instance been destroyed. An destroyed gbean can no longer be used.
     *
     * @return true if the gbean has been destroyed
     */
    public synchronized boolean isDead() {
        return dead;
    }

    /**
     * Gets the reason we are in the current state.
     *
     * @return the reason we are in the current state
     */
    public String getStateReason() {
        return stateReason;
    }

    /**
     * Sets the reason we are in the current state.
     *
     * @param reason The reason we are in the current state
     */
    public void setStateReason(String reason) {
        stateReason = reason;
    }

    /**
     * The java type of the wrapped gbean instance
     *
     * @return the java type of the gbean
     */
    public Class getType() {
        return type;
    }

    public synchronized Object getTarget() {
        return target;
    }

    public final String getObjectName() {
        return abstractName.getObjectName().getCanonicalName();
    }

    public final ObjectName getObjectNameObject() {
        return abstractName.getObjectName();
    }

    public final AbstractName getAbstractName() {
        return abstractName;
    }

    public synchronized final long getStartTime() {
        return startTime;
    }

    public int getState() {
        return gbeanInstanceState.getState();
    }

    public final State getStateInstance() {
        return gbeanInstanceState.getStateInstance();
    }

    /**
     * Gets an unmodifiable map from attribute names to index number (Integer).  This index number
     * can be used to efficiently set or retrieve an attribute value.
     *
     * @return an unmodifiable map of attribute indexes by name
     */
    public Map getAttributeIndex() {
        return Collections.unmodifiableMap(new HashMap(attributeIndex));
    }

    /**
     * Gets an unmodifiable map from operation signature (GOperationSignature) to index number (Integer).
     * This index number can be used to efficciently invoke the operation.
     *
     * @return an unmodifiable map of operation indexec by signature
     */
    public Map getOperationIndex() {
        return Collections.unmodifiableMap(new HashMap(operationIndex));
    }

    /**
     * Gets the GBeanInfo used to build this gbean.
     *
     * @return the GBeanInfo used to build this gbean
     */
    public GBeanInfo getGBeanInfo() {
        return gbeanInfo;
    }

    /**
     * Moves this GBeanInstance to the starting state and then attempts to move this MBean immediately
     * to the running state.
     *
     * @throws IllegalStateException If the gbean is disabled
     */
    public final void start() {
        synchronized (this) {
            if (dead) {
                throw new IllegalStateException("A dead GBean can not be started: abstractName=" + abstractName);
            }
        }
        gbeanInstanceState.start();
    }

    /**
     * Starts this GBeanInstance and then attempts to start all of its start dependent children.
     *
     * @throws IllegalStateException If the gbean is disabled
     */
    public final void startRecursive() {
        synchronized (this) {
            if (dead) {
                throw new IllegalStateException("A dead GBean can not be started: abstractName=" + abstractName);
            }
        }
        gbeanInstanceState.startRecursive();
    }

    /**
     * Moves this GBeanInstance to the STOPPING state, calls stop on all start dependent children, and then attempt
     * to move this MBean to the STOPPED state.
     */
    public final void stop() {
        gbeanInstanceState.stop();
    }

    /**
     * Moves this GBeanInstance to the FAILED state.  There are no calls to dependent children, but they will be
     * notified using standard J2EE management notification.
     */
    final void referenceFailed() {
        gbeanInstanceState.fail();
    }

    /**
     * Gets the gbean data for the gbean held by this gbean mbean.
     *
     * @return the gbean data
     */
    public GBeanData getGBeanData() {
        GBeanData gbeanData = new GBeanData(abstractName, gbeanInfo);

        // copy target into local variables from within a synchronized block to gaurentee a consistent read
        int state;
        Object instance;
        synchronized (this) {
            state = instanceState;
            instance = target;
        }

        // add the attributes
        for (int i = 0; i < attributes.length; i++) {
            GBeanAttribute attribute = attributes[i];
            if (attribute.isPersistent()) {
                String name = attribute.getName();
                Object value;
                if ((state != DESTROYED || attribute.isFramework()) && attribute.isReadable()) {
                    try {
                        value = attribute.getValue(instance);
                    } catch (Throwable throwable) {
                        value = attribute.getPersistentValue();
                        if(log.isDebugEnabled()) {
                            log.debug("Could not get the current value of persistent attribute.  The persistent " +
                                    "attribute will not reflect the current state attribute. " + attribute.getDescription(), throwable);
                        }
                    }
                } else {
                    value = attribute.getPersistentValue();
                }
                gbeanData.setAttribute(name, value);
            }
        }

        // add the references
        for (int i = 0; i < references.length; i++) {
            GBeanReference reference = references[i];
            String name = reference.getName();
            if (reference instanceof GBeanSingleReference) {
                AbstractName abstractName = ((GBeanSingleReference) reference).getTargetName();
                if (abstractName != null) {
                    gbeanData.setReferencePattern(name, abstractName);
                }
            } else if (reference instanceof GBeanCollectionReference) {
                Set patterns = ((GBeanCollectionReference) reference).getPatterns();
                if (patterns != null) {
                    gbeanData.setReferencePatterns(name, patterns);
                }
            } else {
                throw new IllegalStateException("Unrecognized GBeanReference '" + reference.getClass().getName() + "'");
            }
        }
        //TODO copy the dependencies??
        return gbeanData;
    }

    /**
     * Gets the attribute value using the attribute index.  This is the most efficient way to get
     * an attribute as it avoids a HashMap lookup.
     *
     * @param index the index of the attribute
     * @return the attribute value
     * @throws Exception                 if a target instance throws and exception
     * @throws IndexOutOfBoundsException if the index is invalid
     */
    public Object getAttribute(int index) throws Exception {
        GBeanAttribute attribute = attributes[index];

        // copy target into local variables from within a synchronized block to gaurentee a consistent read
        int state;
        Object instance;
        synchronized (this) {
            state = instanceState;
            instance = target;
        }

        if (state != DESTROYED || attribute.isFramework()) {
            return attribute.getValue(instance);
        } else {
            if (attribute.isPersistent()) {
                return attribute.getPersistentValue();
            } else {
                throw new IllegalStateException("Cannot retrieve the value for non-persistent attribute \"" + attribute.getName() + "\" when GBeanInstance is DESTROYED");
            }
        }
    }

    /**
     * Gets an attribute's value by name.  This get style is less efficient becuse the attribute must
     * first be looked up in a HashMap.
     *
     * @param attributeName the name of the attribute to retrieve
     * @return the attribute value
     * @throws Exception                if a problem occurs while getting the value
     * @throws NoSuchAttributeException if the attribute name is not found in the map
     */
    public Object getAttribute(String attributeName) throws NoSuchAttributeException, Exception {
        GBeanAttribute attribute;
        try {
            attribute = getAttributeByName(attributeName);
        } catch (NoSuchAttributeException e) {
            if (attributeName.equals(RAW_INVOKER)) {
                return rawInvoker;
            }
            throw e;
        }

        // copy target into local variables from within a synchronized block to gaurentee a consistent read
        int state;
        Object instance;
        synchronized (this) {
            state = instanceState;
            instance = target;
        }

        if (state != DESTROYED || attribute.isFramework()) {
            return attribute.getValue(instance);
        } else {
            if (attribute.isPersistent()) {
                return attribute.getPersistentValue();
            } else {
                throw new IllegalStateException("Cannot retrieve the value for non-persistent attribute " + attributeName + " when gbean has been destroyed: " + abstractName);
            }
        }
    }

    /**
     * Sets the attribute value using the attribute index.  This is the most efficient way to set
     * an attribute as it avoids a HashMap lookup.
     *
     * @param index the index of the attribute
     * @param value the new value of attribute value
     * @throws Exception                 if a target instance throws and exception
     * @throws IndexOutOfBoundsException if the index is invalid
     */
    public void setAttribute(int index, Object value) throws Exception, IndexOutOfBoundsException {
        setAttribute(index, value, true);
    }

    private void setAttribute(int index, Object value, boolean manage) throws Exception, IndexOutOfBoundsException {
        GBeanAttribute attribute = attributes[index];

        // copy target into local variables from within a synchronized block to gaurentee a consistent read
        int state;
        Object instance;
        synchronized (this) {
            state = instanceState;
            instance = target;
        }

        if (state != DESTROYED || attribute.isFramework()) {
            attribute.setValue(instance, value);
        } else {
            attribute.setPersistentValue(value);
        }
        if (manage && attribute.isManageable()) {
            updateManageableAttribute(attribute, value);
        }
    }

    /**
     * Sets an attribute's value by name.  This set style is less efficient becuse the attribute must
     * first be looked up in a HashMap.
     *
     * @param attributeName the name of the attribute to retrieve
     * @param value         the new attribute value
     * @throws Exception                if a target instance throws and exception
     * @throws NoSuchAttributeException if the attribute name is not found in the map
     */
    public void setAttribute(String attributeName, Object value) throws Exception, NoSuchAttributeException {
        setAttribute(attributeName, value, true);
    }

    public void setAttribute(String attributeName, Object value, boolean manage) throws Exception, NoSuchAttributeException {
        GBeanAttribute attribute = getAttributeByName(attributeName);

        // copy target into local variables from within a synchronized block to gaurentee a consistent read
        int state;
        Object instance;
        synchronized (this) {
            state = instanceState;
            instance = target;
        }

        if (state != DESTROYED || attribute.isFramework()) {
            attribute.setValue(instance, value);
        } else {
            attribute.setPersistentValue(value);
        }
        if (manage && attribute.isManageable()) {
            updateManageableAttribute(attribute, value);
        }
    }

    private void updateManageableAttribute(GBeanAttribute attribute, Object value) {
        if (manageableStore == null) {
            manageableStore = getManageableAttributeStore();
            if (manageableStore == null) {
                return;
            }
        }
        Artifact configName = abstractName.getArtifact();
        if (configName != null) {
            manageableStore.setValue(configName, abstractName, attribute.getAttributeInfo(), value, getBundle());
        } else {
            log.error("Unable to identify Configuration for GBean " + abstractName + ".  Manageable attribute " + attribute.getName() + " was not updated in persistent store.");
        }
    }

    private ManageableAttributeStore getManageableAttributeStore() {
        Set set = kernel.listGBeans(new AbstractNameQuery(ManageableAttributeStore.class.getName()));
        for (Iterator iterator = set.iterator(); iterator.hasNext();) {
            AbstractName abstractName1 = (AbstractName) iterator.next();
            try {
                return (ManageableAttributeStore) kernel.getGBean(abstractName1);
            } catch (GBeanNotFoundException e) {
                // ignored... gbean was unregistered
            }
        }
        return null;
    }

    private GBeanAttribute getAttributeByName(String name) throws NoSuchAttributeException {
        Integer index = attributeIndex.get(name);
        if (index == null) {
            throw new NoSuchAttributeException("Unknown attribute \"" + name + "\" in gbean " + abstractName);
        }
        return attributes[index.intValue()];
    }

    /**
     * Invokes an opreation using the operation index.  This is the most efficient way to invoke
     * an operation as it avoids a HashMap lookup.
     *
     * @param index     the index of the attribute
     * @param arguments the arguments to the operation
     * @return the result of the operation
     * @throws Exception                 if a target instance throws and exception
     * @throws IndexOutOfBoundsException if the index is invalid
     * @throws IllegalStateException     if the gbean instance has been destroyed
     */
    public Object invoke(int index, Object[] arguments) throws Exception {
        GBeanOperation operation = operations[index];

        // copy target into local variables from within a synchronized block to gaurentee a consistent read
        int state;
        Object instance;
        synchronized (this) {
            state = instanceState;
            instance = target;
        }

        if (state == DESTROYED && !operation.isFramework()) {
            throw new IllegalStateException("Operations can only be invoke while the GBean instance is running: " + abstractName);
        }
        return operation.invoke(instance, arguments);
    }

    /**
     * Invokes an operation on the target gbean by method signature.  This style if invocation is
     * inefficient, because the target method must be looked up in a hashmap using a freshly constructed
     * GOperationSignature object.
     *
     * @param operationName the name of the operation to invoke
     * @param arguments     arguments to the operation
     * @param types         types of the operation arguemtns
     * @return the result of the operation
     * @throws Exception                if a target instance throws and exception
     * @throws NoSuchOperationException if the operation signature is not found in the map
     * @throws IllegalStateException    if the gbean instance has been destroyed
     */
    public Object invoke(String operationName, Object[] arguments, String[] types) throws Exception, NoSuchOperationException {
        GOperationSignature signature = new GOperationSignature(operationName, types);
        Integer index = operationIndex.get(signature);
        if (index == null) {
            throw new NoSuchOperationException("Unknown operation " + signature);
        }
        GBeanOperation operation = operations[index.intValue()];

        // copy target into local variables from within a synchronized block to gaurentee a consistent read
        int state;
        Object instance;
        synchronized (this) {
            state = instanceState;
            instance = target;
        }

        if (state == DESTROYED && !operation.isFramework()) {
            throw new IllegalStateException("Operations can only be invoke while the GBean is running: " + abstractName);
        }
        return operation.invoke(instance, arguments);
    }

    boolean createInstance() throws Exception {
        synchronized (this) {
            // first check we are still in the correct state to start
            if (instanceState == CREATING || instanceState == RUNNING) {
                // another thread already completed starting
                return false;
            } else if (instanceState == DESTROYING) {
                // this should never ever happen... this method is protected by the GBeanState class which should
                // prevent stuff like this happening, but check anyway
                stateReason = "an internal error has occurred.  An attempt was made to start an instance that was still stopping which is an illegal state transition.";
                throw new IllegalStateException("A stopping instance can not be started until fully stopped");
            }
            assert instanceState == DESTROYED;

            stateReason = null;

            // Call all start on every reference.  This way the dependecies are held until we can start
            LinkedHashSet<AbstractName> unstarted = new LinkedHashSet<AbstractName>();
            int actualUnstartedSize = 0;
            for (int i = 0; i < dependencies.length; i++) {
                if (dependencies[i].start()) {
                    continue;
                }
                if (unstarted.size() < MAX_DEPENDENCY_STATE_REASON_NUM || MAX_DEPENDENCY_STATE_REASON_NUM == -1) {
                    unstarted.add(dependencies[i].getTargetName());
                }
                actualUnstartedSize++;
            }
            for (int i = 0; i < references.length; i++) {
                if (references[i].start()) {
                    continue;
                }
                if (references[i] instanceof GBeanSingleReference) {
                    if (unstarted.size() < MAX_DEPENDENCY_STATE_REASON_NUM || MAX_DEPENDENCY_STATE_REASON_NUM == -1) {
                        GBeanSingleReference reference = (GBeanSingleReference) references[i];
                        unstarted.add(reference.getTargetName());
                    }
                    actualUnstartedSize++;
                }
            }
            if (!unstarted.isEmpty()) {
                if (unstarted.size() == 1) {
                    stateReason = unstarted.iterator().next() + " did not start.";
                } else {
                    if (actualUnstartedSize == unstarted.size()) {
                        stateReason = "the following dependent services did not start: " + unstarted;
                    } else {
                        stateReason = "there are " + actualUnstartedSize + " dependent services did not start, and the first " + unstarted.size() + " are recored: \n" + unstarted
                                + ". \n You might configure the system property org.apache.geronimo.gbean.runtime.max_state_reason_count to show more service names or -1 to show all the unstarted service names";
                    }
                }
                return false;
            }

            // we are definately going to (try to) start... if this fails the must clean up these variables
            instanceState = CREATING;
            startTime = System.currentTimeMillis();
        }

        for (GBeanReference reference : references) {
            Object value = reference.getProxy();
            if (null != value) {
                objectRecipe.setProperty(reference.getName(), value);
            }
        }

        ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
//        Thread.currentThread().setContextClassLoader(classLoader);
        Object instance = null;
        try {
            try {
                //TODO OSGI NO!
                instance = objectRecipe.create(classLoader);
            } catch (ConstructionException e) {
                Throwable targetException = e.getCause();
                if (targetException instanceof Exception) {
                    stateReason = "the service constructor threw an exception. \n" + printException(targetException);
                    throw (Exception) targetException;
                } else if (targetException instanceof Error) {
                    stateReason = "the service constructor threw an exception. \n" + printException(targetException);
                    throw (Error) targetException;
                }
                stateReason = "the service constructor threw an exception. \n" + printException(e);
                throw e;
            }
            Map<String, Object> unsetProperties = objectRecipe.getUnsetProperties();
            if (unsetProperties.size() > 0) {
                throw new ConstructionException("Error creating gbean of class: " + gbeanInfo.getClassName() + ", attempting to set nonexistent properties: " + unsetProperties.keySet());
            }

            // write the target variable in a synchronized block so it is available to all threads
            // we do this before calling the setters or start method so the bean can be called back
            // from a setter start method
            synchronized (this) {
                target = instance;
            }

            // inject the persistent attribute value into the new instance
            for (GBeanAttribute attribute : attributes) {
                checkIfShouldFail();
                if (!attribute.isDynamic()) {
                    continue;
                }
                try {
                    attribute.inject(target);
                } catch (Exception e) {
                    stateReason = "the setter for attribute '" + attribute.getName() + "' threw an exception. \n" + printException(e);
                    throw e;
                }
            }

            if (instance instanceof GBeanLifecycle) {
                checkIfShouldFail();
                try {
                    ((GBeanLifecycle) instance).doStart();
                } catch (Exception e) {
                    stateReason = "the doStart method threw an exception. \n" + printException(e);
                    throw e;
                }
            }

            // all done... we are now fully running
            synchronized (this) {
                checkIfShouldFail();
                if (instanceRegistry != null) {
                    instanceRegistry.instanceCreated(instance, this);
                }
                if (gbeanInfo.isOsgiService()) {
                    String[] serviceInterfaces;
                    if (this.serviceInterfaces != null) {
                        serviceInterfaces = this.serviceInterfaces;
                    } else if (instance instanceof ServiceInterfaces) {
                        serviceInterfaces = ((ServiceInterfaces)instance).getServiceInterfaces();
                    } else if (gbeanInfo.getServiceInterfaces().length > 0) {
                        serviceInterfaces = gbeanInfo.getServiceInterfaces();
                    } else {
                        Set<String> classes = new HashSet<String>(gbeanInfo.getInterfaces());
                        classes.add(gbeanInfo.getClassName());
                        serviceInterfaces = classes.toArray(new String[classes.size()]);
                    }
                    Dictionary serviceProperties;
                    if (this.serviceProperties != null) {
                        serviceProperties = this.serviceProperties;
                    } else {
                        serviceProperties = new Hashtable();
                    }
                    serviceProperties.put(ABSTRACT_NAME_PROPERTY, abstractName.toString());
                    if (serviceProperties.get(OSGI_JNDI_NAME_PROPERTY) == null) {
                        serviceProperties.put(OSGI_JNDI_NAME_PROPERTY, kernel.getNaming().toOsgiJndiName(abstractName));
                    }
                    serviceRegistration = bundleContext.registerService(serviceInterfaces, instance, serviceProperties);
                    if (log.isDebugEnabled()) {
                        log.debug("Registered gbean " + abstractName + " as osgi service under interfaces " + Arrays.asList(serviceInterfaces) + " with properties " + serviceProperties);
                    }
                }
                instanceState = RUNNING;
                this.notifyAll();
            }

            stateReason = null;
            return true;
        } catch (Throwable t) {
            stateReason = "Throwable during start of gbean: \n" + printException(t);
            // something went wrong... we need to destroy this instance
            synchronized (this) {
                instanceState = DESTROYING;
            }

            if (instance instanceof GBeanLifecycle) {
                try {
                    ((GBeanLifecycle) instance).doFail();
                } catch (Throwable ignored) {
                    log.error("Problem in doFail of " + abstractName, ignored);
                }
            }

            // bean has been notified... drop our reference
            synchronized (this) {
                // stop all of the references
                for (int i = 0; i < references.length; i++) {
                    references[i].stop();
                }
                for (int i = 0; i < dependencies.length; i++) {
                    dependencies[i].stop();
                }

                target = null;
                instanceState = DESTROYED;
                startTime = 0;
                this.notifyAll();
            }

            if (t instanceof Exception) {
                throw (Exception) t;
            } else if (t instanceof Error) {
                throw (Error) t;
            } else {
                throw new Error(t);
            }
        } finally {
            Thread.currentThread().setContextClassLoader(oldCL);
        }
    }

    private String printException(Throwable t) {
        StringWriter stringWriter = new StringWriter();
        PrintWriter printWriter = new PrintWriter(stringWriter);
        t.printStackTrace(printWriter);
        printWriter.flush();
        return stringWriter.toString();
    }

    private synchronized void checkIfShouldFail() throws Exception {
        if (shouldFail) {
            shouldFail = false;
            throw new Exception("A reference has failed so construction can not complete");
        }
    }

    boolean destroyInstance(boolean stop) throws Exception {
        Object instance;
        synchronized (this) {
            if (!stop && instanceState == CREATING) {
                // signal to the creating thead that it should fail
                shouldFail = true;
                return false;
            }

            // if the instance is being created we need to wait
            //  for it to finish before we can try to stop it
            while (instanceState == CREATING) {
                // todo should we limit this wait?  If so, how do we configure the wait time?
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    // clear the interrupted flag
                    Thread.interrupted();
                    // rethrow the interrupted exception.... someone was sick of us waiting
                    throw e;
                }
            }

            if (instanceState == DESTROYING || instanceState == DESTROYED) {
                // another thread is already stopping or has already stopped
                return false;
            }
            assert instanceState == RUNNING;
            stateReason = null;

            // we are definately going to stop... if this fails the must clean up these variables
            instanceState = DESTROYING;
            instance = target;
        }

        // update the persistent attributes
        // do not update the persistent attibute values in the case of a failure
        // failed gbeans may have corrupted attributes that would be persisted
        Exception problem = null;
        if (stop && instance != null) {
            try {
                // get all the data but don't update in case there is an exception
                Map data = new HashMap();
                for (int i = 0; i < attributes.length; i++) {
                    GBeanAttribute attribute = attributes[i];
                    if (attribute.isPersistent() && attribute.isReadable()) {
                        // copy the current attribute value to the persistent value
                        Object value;
                        try {
                            value = attribute.getValue(instance);
                        } catch (Throwable e) {
                            // There is no reason to create a new Exception sub class as this exception will
                            // simply be caught and logged on GBeanInstanceState
                            throw new Exception("Problem while updating the persistent value of attibute: " +
                                    "Attribute Name: " + attribute.getName() + ", " +
                                    "Type: " + attribute.getType() + ", " +
                                    "GBeanInstance: " + getName(), e);
                        }
                        data.put(attribute, value);
                    }
                }
                // now we have all the data we can update the persistent values
                for (int i = 0; i < attributes.length; i++) {
                    GBeanAttribute attribute = attributes[i];
                    if (attribute.isPersistent() && attribute.isReadable()) {
                        // copy the current attribute value to the persistent value
                        Object value = data.get(attribute);
                        attribute.setPersistentValue(value);
                    }
                }
            } catch (Exception e) {
                // the getter threw an exception; now we must to fail
                stop = false;
                problem = e;
            }
        }

        // we notify the bean before removing our reference so the bean can be called back while stopping
        ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
//        Thread.currentThread().setContextClassLoader(classLoader);
        try {
            if (instance instanceof GBeanLifecycle) {
                if (stop) {
                    try {
                        ((GBeanLifecycle) instance).doStop();
                    } catch (Throwable ignored) {
                        log.error("Problem in doStop of " + abstractName, ignored);
                    }
                } else {
                    try {
                        ((GBeanLifecycle) instance).doFail();
                    } catch (Throwable ignored) {
                        log.error("Problem in doFail of " + abstractName, ignored);
                    }
                }
            }
        } finally {
            Thread.currentThread().setContextClassLoader(oldCL);
        }

        // bean has been notified... drop our reference
        synchronized (this) {
            // stop all of the references
            for (int i = 0; i < references.length; i++) {
                references[i].stop();
            }
            for (int i = 0; i < dependencies.length; i++) {
                dependencies[i].stop();
            }

            target = null;
            instanceState = DESTROYED;
            if (instanceRegistry != null) {
                instanceRegistry.instanceDestroyed(instance);
            }
            if (serviceRegistration != null) {
                serviceRegistration.unregister();
                serviceRegistration = null;
                if (log.isDebugEnabled()) {
                    log.debug("unregistered gbean as osgi service: " + abstractName);
                }
            }
            startTime = 0;
        }

        if (problem != null) {
            throw problem;
        }
        return true;
    }

    private void addManagedObjectAttributes(Map<String, GBeanAttribute> attributesMap) {
        //
        //  Special attributes
        //
        attributesMap.put("abstractName",
                GBeanAttribute.createSpecialAttribute(attributesMap.get("abstractName"),
                        this,
                        "abstractName",
                        AbstractName.class,
                        getAbstractName()));

        attributesMap.put("objectName",
                GBeanAttribute.createSpecialAttribute(attributesMap.get("objectName"),
                        this,
                        "objectName",
                        String.class,
                        getObjectName()));

        attributesMap.put("classLoader",
                GBeanAttribute.createSpecialAttribute(attributesMap.get("classLoader"),
                        this,
                        "classLoader",
                        ClassLoader.class,
                        classLoader));

        attributesMap.put("bundle",
                GBeanAttribute.createSpecialAttribute(attributesMap.get("bundle"),
                        this,
                        "bundle",
                        Bundle.class,
                        bundleContext.getBundle()));
        attributesMap.put("bundleContext",
                GBeanAttribute.createSpecialAttribute(attributesMap.get("bundleContext"),
                        this,
                        "bundleContext",
                        BundleContext.class,
                        bundleContext));

        attributesMap.put("kernel",
                GBeanAttribute.createSpecialAttribute(attributesMap.get("kernel"),
                        this,
                        "kernel",
                        Kernel.class,
                        kernel));

    }

    private GBeanInfo rebuildGBeanInfo(GConstructorInfo constructor,
                                       String j2eeType,
                                       int priority,
                                       boolean osgiService,
                                       String[] serviceInterfaces) {
        Set<GAttributeInfo> attributeInfos = new HashSet<GAttributeInfo>();
        for (int i = 0; i < attributes.length; i++) {
            GBeanAttribute attribute = attributes[i];
            attributeInfos.add(attribute.getAttributeInfo());
        }
        Set<GOperationInfo> operationInfos = new HashSet<GOperationInfo>();
        for (int i = 0; i < operations.length; i++) {
            operationInfos.add(operations[i].getOperationInfo());
        }

        Set<GReferenceInfo> referenceInfos = new HashSet<GReferenceInfo>();
        for (int i = 0; i < references.length; i++) {
            referenceInfos.add(references[i].getReferenceInfo());
        }

        Set<String> interfaceInfos = new HashSet<String>();
        for (int i = 0; i < interfaces.length; i++) {
            interfaceInfos.add(interfaces[i]);
        }

        return new GBeanInfo(null,
                name,
                type.getName(),
                j2eeType,
                attributeInfos,
                constructor,
                operationInfos,
                referenceInfos,
                interfaceInfos,
                priority,
                osgiService,
                serviceInterfaces);
    }

    public boolean equals(Object obj) {
        if (obj == this) return true;
        if (!(obj instanceof GBeanInstance)) return false;
        return abstractName.equals(((GBeanInstance) obj).abstractName);
    }

    public int hashCode() {
        return abstractName.hashCode();
    }

    public String toString() {
        return abstractName.toString();
    }
}

redpajama_set_name: RedPajamaGithub


text:
@interface UISearchBar (Common)

@property (nonatomic,strong)UIColor *backgroundColor;

- (void)insertBGColor;

@end


text:
'use strict';

// Dependencies
const moment = require('moment')

module.exports = function setup() {
  return function plugin(files, aldous, done) {
    setImmediate(done)
    files.forEach(function(file) {
      if (file.date) {
        file.date = moment(file.date)
      }
    })
  }
}


text:
using System.Windows;

namespace Igniter.Tests.Live
{
    [LiveTest("Command Parameter")]
    public partial class CommandParameterTestWindow : Window
    {
        public CommandParameterTestWindow()
        {
            DataContext = new CommandParameterTestViewModel();

            InitializeComponent();
        }
    }
}


text:
title:  "{::nomarkdown}Doofe Mama!{:/}"
date:   2019-04-15 10:00:00 +0200
header:
  teaser: ../../../../../images/schwesternliebe_teaser.png
tags: ["Kleinkind", "Sozialleben"]
---

**"Ich male nie wieder für dich. Nur noch für den Papa. Ich hab dich gar nicht mehr lieb. Geh weg du alter Pups!" Wir steuern auf den 4. Geburtstag zu und ich bekomme eine Ahnung von der sogenannten Kleinkind-Pubertät.**

Unfassbar, dass diese liebevolle große Schwester so eine Kratzbürste sein kann.

Der Samstag war hart. Mit steifem Nacken bin ich aufgewacht, weil meine Johanna wieder zu mir ins Bett gekrabbelt ist. Sie schläft direkt neben unserem Bett. In einem Kinderbett, das zu uns hin offen ist. Also eine durchgehende Liegefläche. Wenn ich sie schlafen gebracht habe, lege ich immer das Stillkissen zwischen sie und mich, damit sie mir nachts nicht so viel Platz wegnimmt. Doch das hilft nur selten. Irgendwie und irgendwann krabbelt sie rüber und liegt entweder bei mir oder meinem Mann. Pauline findet irgendwo dazwischen Platz. Wir waren vor Kurzem auch Doppelstockbetten angucken und die Girls waren schwer begeistert. Wir überlegen, eines zum 4. Geburtstag anzuschaffen und dann könnten die Mädchen gleichzeitig ins Kinderzimmer ziehen. Also für die Nächte. Tagsüber ist das Kinderzimmer eh schon beliebt. Doch zurück zum Thema.

Johanna wachte in meinen Arm auf und alles war bestens. Dann standen wir auf (um 5.30 Uhr übrigens, danke Kinder!) und ich bereitete Pfannkuchen zum Frühstück. So. Und irgendwann zwischen Pfannkuchen zwei und drei muss ich irgendetwas gesagt oder getan haben, das den Groll meiner Großen auf sich zog. Denn von da an war ich für sie gestorben. Und wie sie dann schaut!! Kennt hier jemand die gruseligen Kinder aus Shining? Nachdem sie mir den ganzen Vormittag schon übelste Drohungen an den Kopf geworfen hat ("Und dann pullere ich extra in die schöne Hose!"), stand sie mittags mit schmalen Augen und zusammengezogenen Brauen vor unserem Bett. Ich legte gerade Pauline schlafen. Da schaute Johanna böse und meinte nur: "Kuschel ruhig mit Baby. Mit mir wirst du nämlich nie wieder kuscheln!". Dann verschwand sie in einer Wolke dünnen, blonden Haares die Treppe hinunter um ihren Vater fröhlich um eine Runde Maulwurf-Spiel zu bitten. Boah…

Ich weiß in diesen Situationen immer gar nicht so recht, was ich davon halten soll. Ich weiß, dass es altersgerecht und eigentlich was Gutes ist. Sie ist sich meiner Liebe so sicher, dass sie mir ein "Alter Po" an den Kopf werfen darf. Und diese Laune ist auch immer genau so schnell verflogen, wie sie kam. Aber trotzdem geht es nicht spurlos an mir vorüber. Es tut wirklich weh. Mein Baby. Das Mäuschen dass Zeter und Mordio brüllte, wenn es mal kurz auf Papas Arm sollte. Die gleich Maus, die kichernd auf dem Wickeltisch lag, die ihre kleinen Ärmchen um mich schlingt, wenn sie sich freut, dass ich sie aus der Kita abholen komme. Sie wird jetzt immer selbstständiger. Entscheidet selbst, wen sie nachmittags treffen möchte. Was sie anziehen oder spielen will Und eben auch auf wen sie heute böse ist. Hoffentlich geht das schnell wieder vorbei. Ich bin nämlich kein alter Pups. Auch wenn gewisse kleine Mädchen gegenteiliges behaupten…


text:
source ~/.bashrc
cd /home/ubuntu/myapp
npm install


text:
<?php
/**
 * sfWidgetFormPropelSelect represents a select HTML tag with Ajax support for a model.
 *
 * @package    symfony
 * @subpackage widget
 * @author     Ahmed El.Hussaini <eng.ahmed.elhussaini@sandbox-ws.com>
 */
class sfWidgetFormPropelSelectAjax extends sfWidgetFormPropelSelect
{
  /**
   *  Constructor.
   *
   *  Available options:
   *
   *  - url:                The url of the action(routing, or module/action) to be called using Ajax (required)
   *  - update:             The ID of the HTML element to be updated (model_name_update by default)
   *  - with:               List of parameters to be sent with the Ajax request (value of the selected select option is added by default as a parameter called id)
   *  - complete:           A function to be called when the request finishes (after success and error callbacks are executed, null by default)
   *  - error:              A function to be called if the request fails (null by default)
   *  - beforeSend:         A pre-callback to modify the XMLHttpRequest object before it is sent
   *  - event:              The DOM event of the select tag that will trigger the Ajax call (onchange by default)
   *  - update_element:     The HTML element rendered that will be updated with the Ajax response (div by default)
   *
   *  Usage:
   *

   *
   *    The following example creates a drop down list that sends an Ajax request to the action "test/ajax" on change of the select menu.
   *    By default if you don't specify the update option, the widget renders an empty div element with an id in the format
   *    model_name_update.
   *
   *
   *    $this->widgetSchema['category'] = new sfWidgetFormPropelSelectAjax(array(
   *	    'model' => 'Category',
   *	    'method' => 'getName',
   *	    'url' => 'test/ajax'
   *    ));
   *
   *
   *  The above code will render the following HTML code
   *
   *
   *    Category
   *    <select id="category_category" name="category[category]">
   *      <option value="2">Fun</option>
   *      <option value="3">Stuff</option>
   *    </select>
   *

   *
   *
   *
   *  If you want to change the id of the generated div or change the div to lets say a span use the following
   *
   *    'update' => 'foobar'
   *
   *
   *
   *    'update_element' => 'span'
   *
   *
   *  NOTE: If you add the update option with a value other than the default one added automatically by the widget
   *  you will have to add the HTML element to be updated manually in the template.
   *
   * @param array $options     An array of options
   * @param array $attributes  An array of default HTML attributes
   *
   * @see sfWidgetFormPropelSelect
  */
  protected function configure($options = array(), $attributes = array()) {
    parent::configure($options, $attributes);
    $this->addRequiredOption('url');
    $this->addOption('update', strtolower($options['model']).'_update');
    $this->addOption('with', null);
    $this->addOption('complete', null);
    $this->addOption('error', null);
    $this->addOption('beforeSend', null);
    $this->addOption('event', 'change');
    $this->addOption('update_element', 'div');
  }

  /**
   * @param  string $name        The element name
   * @param  string $value       The value selected in this widget
   * @param  array  $attributes  An array of HTML attributes to be merged with the default HTML attributes
   * @param  array  $errors      An array of errors for the field
   *
   * @return string An HTML select tag string plus jQuery ajax script
   *
   * @see sfWidgetForm
  */
  public function render($name, $value  = null, $attributes = array(), $errors = array())
  {
    $default_update = true;
    $update = '';
    if ($this->getOption('update') == strtolower($this->getOption('model')).'_update')
    {
      $update = strtolower($this->getOption('model')).'_update';
    }
    else
    {
      $update = $this->getOption('update');
      $default_update = false;
    }
    $optional = '';

    $optional .= sfJQueryUtilities::getCompleteOption($this->getOption('complete'));
    $optional .= sfJQueryUtilities::getBeforeSendOption($this->getOption('beforeSend'));
    $optional .= sfJQueryUtilities::getErrorOption($this->getOption('error'));

    // call parent render method
    $html = parent::render($name, $value, $attributes, $errors);
    if($default_update)
    {
      if (!is_null($this->getOption('update_element')))
      {
        // add defined HTML element
        $html .= '<'.$this->getOption('update_element').' id="'.$this->getOption('update').'"></'.$this->getOption('update_element').'>';
      }
      else
      {
        // use default HTML element
        $html .= '
getOption('update').'">
';
      }
    }

    // add ajax code to the defined event
    $html .= sprintf(<<<EOF

EOF
      ,
      $this->generateId($name),
      $this->getOption('event'),
      url_for($this->getOption('url')),
      $update,
      $optional
    );

    return $html;
  }

  public function getJavascripts()
  {
    return array('/sfJqueryWidgetsPlugin/js/jquery-1.2.6.min.js');
  }

}


text:
ACCEPTED

#### According to
Interim Register of Marine and Nonmarine Genera

#### Published in
Bull. Res. Coun. Israel 6B: 241.

#### Original name
null

### Remarks
null


text:
@implementation ZKJProgressView

- (void)awakeFromNib
{
    [super awakeFromNib];
    self.roundedCorners = 2;
    self.progressLabel.textColor = [UIColor whiteColor];
}

- (void)setProgress:(CGFloat)progress animated:(BOOL)animated
{
    [super setProgress:progress animated:animated];
    NSString *proStr = [NSString stringWithFormat:@"%.0f%%", progress * 100];
    self.progressLabel.text = [proStr stringByReplacingOccurrencesOfString:@"-" withString:@""];
}

@end


text:
import { Component, Input, ElementRef, OnInit, PipeTransform, Pipe, ViewEncapsulation, OnDestroy } from '@angular/core';
import { VgAPI } from '../../core/services/vg-api';
import { Subscription } from 'rxjs';

// Workaround until we can use UTC with Angular Date Pipe
@Pipe({ name: 'vgUtc' })
export class VgUtcPipe implements PipeTransform {
    transform(value: number, format: string): string {
        let date = new Date(value);
        let result = format;
        let ss: string|number = date.getUTCSeconds();
        let mm: string|number = date.getUTCMinutes();
        let hh: string|number = date.getUTCHours();

        if (ss < 10) {
            ss = '0' + ss;
        }
        if (mm < 10) {
            mm = '0' + mm;
        }
        if (hh < 10) {
            hh = '0' + hh;
        }

        result = result.replace(/ss/g, <string>ss);
        result = result.replace(/mm/g, <string>mm);
        result = result.replace(/hh/g, <string>hh);

        return result;
    }
}

@Component({
    selector: 'vg-time-display',
    encapsulation: ViewEncapsulation.None,
    template: `
        LIVE
        {{ getTime() | vgUtc:vgFormat }}
        <ng-content></ng-content>
    `,
    styles: [ `
        vg-time-display {
            -webkit-touch-callout: none;
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
            display: flex;
            justify-content: center;
            height: 50px;
            width: 60px;
            cursor: pointer;
            color: white;
            line-height: 50px;
            pointer-events: none;
            font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
        }
    ` ]
})
export class VgTimeDisplay implements OnInit, OnDestroy {
    @Input() vgFor: string;
    @Input() vgProperty = 'current';
    @Input() vgFormat = 'mm:ss';

    elem: HTMLElement;
    target: any;

    subscriptions: Subscription[] = [];

    constructor(ref: ElementRef, public API: VgAPI) {
        this.elem = ref.nativeElement;
    }

    ngOnInit() {
        if (this.API.isPlayerReady) {
            this.onPlayerReady();
        }
        else {
            this.subscriptions.push(this.API.playerReadyEvent.subscribe(() => this.onPlayerReady()));
        }
    }

    onPlayerReady() {
        this.target = this.API.getMediaById(this.vgFor);
    }

    getTime() {
        let t = 0;

        if (this.target) {
            t = Math.round(this.target.time[ this.vgProperty ]);
            t = isNaN(t) || this.target.isLive ? 0 : t;
        }

        return t;
    }

    ngOnDestroy() {
        this.subscriptions.forEach(s => s.unsubscribe());
    }
}


text:
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.gradle.tooling;

import org.gradle.api.Project;
import org.gradle.internal.impldep.com.google.gson.GsonBuilder;
import org.gradle.util.GradleVersion;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * Intended to be used only for reporting of custom {@link ModelBuilderService}s unhandled failures.
 * <p>
 * Use {@link ModelBuilderContext#report} for errors, warnings detected by your {@link ModelBuilderService}.
 *
 * @author Vladislav.Soroka
 * @see MessageBuilder
 * @see ModelBuilderContext#report
 */
public final class ErrorMessageBuilder {
  @NotNull private final Project myProject;
  @Nullable private final Exception myException;
  @NotNull private final String myGroup;
  @Nullable private String myDescription;

  private ErrorMessageBuilder(@NotNull Project project, @Nullable Exception exception, @NotNull String group) {
    myProject = project;
    myException = exception;
    myGroup = group;
  }

  public static ErrorMessageBuilder create(@NotNull Project project, @NotNull String group) {
    return new ErrorMessageBuilder(project, null, group);
  }

  public static ErrorMessageBuilder create(@NotNull Project project, @Nullable Exception exception, @NotNull String group) {
    return new ErrorMessageBuilder(project, exception, group);
  }

  public ErrorMessageBuilder withDescription(@NotNull String description) {
    myDescription = description;
    return this;
  }

  /**
   * @deprecated use {@link ModelBuilderContext#report} instead
   */
  @ApiStatus.ScheduledForRemoval
  @Deprecated
  public String build() {
    Message message = buildMessage();
    return new GsonBuilder().create().toJson(message);
  }

  @ApiStatus.Internal
  public Message buildMessage() {
    String message = myDescription != null ? myDescription : "";
    String projectDisplayName = getDisplayName(myProject);
    String title = null;
    if (myException != null) {
      title = getRootCauseMessage(myException);
    }
    if (title == null) {
      title = myDescription != null ? myDescription : myGroup;
    }
    title = projectDisplayName + ": " + title;
    return MessageBuilder.create(title, message)
      .warning() // custom model builders failures often not so critical to the import results and reported as warnings to avoid useless distraction
      .withException(myException)
      .withGroup(myGroup)
      .withLocation(myProject.getBuildFile().getPath(), 0, 0)
      .build();
  }

  @NotNull
  private static String getDisplayName(@NotNull Project project) {
    String projectDisplayName;
    if (GradleVersion.current().getBaseVersion().compareTo(GradleVersion.version("3.3")) < 0) {
      StringBuilder builder = new StringBuilder();
      if (project.getParent() == null && project.getGradle().getParent() == null) {
        builder.append("root project '");
        builder.append(project.getName());
        builder.append('\'');
      }
      else {
        builder.append("project '");
        builder.append(project.getPath());
        builder.append("'");
      }
      projectDisplayName = builder.toString();
    }
    else {
      projectDisplayName = project.getDisplayName();
    }
    return projectDisplayName;
  }

  @Nullable
  private static String getRootCauseMessage(@NotNull Throwable t) {
    Throwable e = t;
    while (true) {
      if (e.getCause() == null) {
        String message = e.getMessage();
        return message == null ? t.getMessage() : message;
      }
      e = e.getCause();
    }
  }
}


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>kr.bydelta.koala.rhino</title>
<meta name="date" content="2018-03-19">
<link rel="stylesheet" type="text/css" href="../../../../stylesheet.css" title="Style">

kr.bydelta.koala.rhino

Classes

Dictionary

Dictionary$

RhinoTaggerCLISpec

Tagger


text:
<!DOCTYPE html>

    <meta charset="utf-8">

    <link rel="apple-touch-icon" sizes="180x180" href="/static/favicon/apple-touch-icon.png">
<link rel="icon" type="image/png" href="/static/favicon/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="/static/favicon/favicon-16x16.png" sizes="16x16">
<link rel="manifest" href="/static/favicon/manifest.json">
<link rel="mask-icon" href="/static/favicon/safari-pinned-tab.svg" color="#5bbad5">
<link rel="shortcut icon" href="/static/favicon/favicon.ico">
<meta name="msapplication-config" content="/static/favicon/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<meta name="viewport" content="width=device-width, initial-scale=1">

    <link href="https://fonts.googleapis.com/css?family=Open+Sans:300" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet">
<link rel="stylesheet" href="/static/css/style.css">

    <title>

    Amet - Flattening a Python dictionary as environment variables - maurodec.com

    </title>

        Home

            Blog
            About me
            Source

Amet - Flattening a Python dictionary as environment variables

        April 20 - 2017

            Python

            Amet

            Open Source

I recently had to build an ETL job in Python that was initially going to be
deployed on AWS. Little did I know that a last minute change from AWS to
Heroku would cause me to change how the job’s configuration was going to be
read significantly.

A bit of Background

ETL jobs do not usually require much interaction. You pretty much just need to
figure out how to pass it some configuration values (such as a database
connection string). You can do this in several ways, but probably the easiest
are to either read everything from sys.argv or to use a configuration file. I
tend to go for the latter, as I cannot be bothered to parse CLI arguments, plus
it is a lot easier to share and swap configuration files instead of command
line arguments. As for configuration files I tend to favor JSON over other
formats, as it is easy to read/write by humans, allows for lists and nested
objects and the json module makes reading these files trivial.

As I said before, this was initially going to run on AWS, but it was later
decided that it would be run in Heroku. This is usually not a problem, unless
you decided that your configuration would reside on configuration files.

The problem

The downside to configuration files is that since you usually keep secret
values in them you should not add them to version control systems such as git
(yes, even if your repository is private). This can become a problem with
some environments such as Heroku where you have no way of pushing you config
files. You should, in this cases, use environment variables for configuration.

Changing from configuration files to environment variables poses several
obvious problems. First and foremost some code will have to be changed to
accommodate this new requirement. Not only that, working with environment
variables is not nearly as user friendly as a JSON file, but worst of all,
environment variables are “flat”, meaning that you cannot have nested values
(and no, trying to encode something like a JSON object into an environment
variable isn’t even an option).

The solution

The solution I came up with was relatively simple. I wrote a function that
will attempt to fill a prototype configuration dictionary with the expected
configuration values. It does this by iterating through the dictionary and,
for every key whose value is not a dictionary, looks for an environment
variable whose name is the same as the key. However, if the value is a
dictionary, it will recursively call itself and do the same, although in this
case the key containing this dictionary will be taken into account when
building the variable’s name.

A simplified pseudocode version of the function looks like:

As you can see this has its own problems. Without any extra work, any int
values will not be converted automatically, probably making it infuriatingly
inconsistent. This method also does not support lists without doing some
probably ugly things. Finally, in some cases names may clash, although that
would be highly improbable (and would probably mean you’re using terrible
names for keys anyway).

Up until this point, however, we only cared about reading values and not
writing them. Unless we want to create those environment variables manually
(which I do not recommend) we also need some code to generate the key value
pairs for us.  This is even simpler than reading.

A simplified pseudocode version of the function looks like:

After we have our dictionary of variable names as keys we can either
export them or (in my case)
call the Heroku API
so they are set in my app’s configuration.

Amet - The solution, packaged.

I wrote a library in Pythom, Amet, that packages these two functions so
that they can be used from any Python script. The code with instructions can
be found here.

Amet provides two functions, load_from_environment and dump to help with
reading and creating any relevant environment variables. It also provides some
extras such as automatic parsing of types and some error handling. This means
that if you are expecting an environment variable to be an int, float, or
bool value, it will be automatically converted for you

The library is still pretty green, so any contributions are more than welcome.

I hope it works well for you and saves you time and headaches 😁.

Made with ❤ by Mauro de Carvalho using Hugo.

Github &#9679 mauro@maurodec.com &#9679 LinkedIn


text:
from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.
def index(req):
    return HttpResponse('')