diff --git a/Modules/QtWidgets/include/QmitkNodeSelectionButton.h b/Modules/QtWidgets/include/QmitkNodeSelectionButton.h
index 2b400c5900..111c63a34a 100644
--- a/Modules/QtWidgets/include/QmitkNodeSelectionButton.h
+++ b/Modules/QtWidgets/include/QmitkNodeSelectionButton.h
@@ -1,71 +1,71 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef QmitkNodeSelectionButton_h
#define QmitkNodeSelectionButton_h
#include
#include
#include
#include
/**
* @class QmitkNodeSelectionButton
* @brief Button class that can be used to display information about a given node.
* If the given node is a nullptr the node info text will be shown.
-* The node info can be formated text (e.g. HTML code; like the tooltip text).
+* The node info can be formatted text (e.g. HTML code; like the tooltip text).
*/
class MITKQTWIDGETS_EXPORT QmitkNodeSelectionButton : public QPushButton
{
Q_OBJECT
public:
explicit QmitkNodeSelectionButton(QWidget *parent = nullptr);
~QmitkNodeSelectionButton() override;
const mitk::DataNode* GetSelectedNode() const;
bool GetSelectionIsOptional() const;
public Q_SLOTS:
virtual void SetSelectedNode(const mitk::DataNode* node);
virtual void SetNodeInfo(QString info);
/** Set the widget into an optional mode. Optional means that the selection of no valid
node does not mean an invalid state. Thus no node is a valid "node" selection too.
The state influences if the info text is handled as an information (optional) or a
warning (optiona==false).*/
void SetSelectionIsOptional(bool isOptional);
protected:
void paintEvent(QPaintEvent *p) override;
void changeEvent(QEvent *event) override;
void AddNodeObserver();
void RemoveNodeObserver();
void OnNodeModified(const itk::Object * /*caller*/, const itk::EventObject &);
mitk::DataNode::ConstPointer m_SelectedNode;
QString m_Info;
bool m_OutDatedThumbNail;
QPixmap m_ThumbNail;
itk::ModifiedTimeType m_DataMTime;
itk::ModifiedTimeType m_SelectionPropMTime;
bool m_IsOptional;
unsigned long m_NodeModifiedObserverTag;
bool m_NodeObserved;
};
#endif
diff --git a/Modules/QtWidgets/include/QmitkSingleNodeSelectionWidget.h b/Modules/QtWidgets/include/QmitkSingleNodeSelectionWidget.h
index 2ce34485c9..44130cb7e6 100644
--- a/Modules/QtWidgets/include/QmitkSingleNodeSelectionWidget.h
+++ b/Modules/QtWidgets/include/QmitkSingleNodeSelectionWidget.h
@@ -1,97 +1,97 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef QmitkSingleNodeSelectionWidget_h
#define QmitkSingleNodeSelectionWidget_h
#include
#include
#include
#include
#include
#include
#include
class QmitkAbstractDataStorageModel;
/**
* @class QmitkSingleNodeSelectionWidget
* @brief Widget that represents a node selection of (max) one node. It acts like a button. Clicking on it
* allows to change the selection.
*
* @remark This class provides a public function 'SetAutoSelectNewNodes' that can be used to enable
* the auto selection mode (default is false).
* The user of this class calling this function has to make sure that the base-class Q_SIGNAL
* 'CurrentSelectionChanged', which will be emitted by this function, is already
* connected to a receiving slot, if the initial valid auto selection should not get lost.
*/
class MITKQTWIDGETS_EXPORT QmitkSingleNodeSelectionWidget : public QmitkAbstractNodeSelectionWidget
{
Q_OBJECT
public:
explicit QmitkSingleNodeSelectionWidget(QWidget* parent = nullptr);
mitk::DataNode::Pointer GetSelectedNode() const;
bool GetAutoSelectNewNodes() const;
using NodeList = QmitkAbstractNodeSelectionWidget::NodeList;
public Q_SLOTS:
void SetCurrentSelectedNode(mitk::DataNode* selectedNode);
/**
* Sets the auto selection mode (default is false).
- * If auto select is true and the following conditions are fullfilled, the widget will
+ * If auto select is true and the following conditions are fulfilled, the widget will
* select a node automatically from the data storage:
* - a data storage is set
* - data storage contains at least one node that matches the given predicate
* - no selection is set
*
* @remark Enabling the auto selection mode by calling 'SetAutoSelectNewNodes(true)'
* will directly emit a 'QmitkSingleNodeSelectionWidget::CurrentSelectionChanged' Q_SIGNAL
* if a valid auto selection was made.
* If this initial emission should not get lost, auto selection mode needs to be enabled after this
* selection widget has been connected via the 'QmitkSingleNodeSelectionWidget::CurrentSelectionChanged'
* Q_SIGNAL to a receiving function.
*/
void SetAutoSelectNewNodes(bool autoSelect);
protected Q_SLOTS:
virtual void OnClearSelection();
protected:
void ReviseSelectionChanged(const NodeList& oldInternalSelection, NodeList& newInternalSelection) override;
bool eventFilter(QObject *obj, QEvent *ev) override;
void EditSelection();
void UpdateInfo() override;
void OnDataStorageChanged() override;
void OnNodeAddedToStorage(const mitk::DataNode* node) override;
void AutoSelectNodes();
/** Helper function that gets a suitable auto selected node from the datastorage that fits to the predicate settings.
- @param ignoreNodes You may pass a list of nodes that must not be choosen as auto selected node. */
+ @param ignoreNodes You may pass a list of nodes that must not be chosen as auto selected node. */
mitk::DataNode::Pointer DetermineAutoSelectNode(const NodeList& ignoreNodes = {});
/** See documentation of SetAutoSelectNewNodes for details*/
bool m_AutoSelectNodes;
Ui_QmitkSingleNodeSelectionWidget m_Controls;
};
#endif
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.cpp
index 883633b384..73d64e883f 100644
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.cpp
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.cpp
@@ -1,259 +1,259 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include "QmitkContourModelToImageWidget.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static const char* const HelpText = "Select a image and a contour(set)";
class QmitkContourModelToImageWidgetPrivate
{
public:
QmitkContourModelToImageWidgetPrivate();
~QmitkContourModelToImageWidgetPrivate();
/** @brief Check if selections is valid. */
void SelectionControl( unsigned int index, const mitk::DataNode* selection);
- /** @brief Enable buttons if data selction is valid. */
+ /** @brief Enable buttons if data selection is valid. */
void EnableButtons(bool enable = true);
/** @brief Does the actual contour filling */
mitk::LabelSetImage::Pointer FillContourModelSetIntoImage(mitk::Image *image, mitk::ContourModelSet *contourSet, mitk::TimePointType timePoint);
Ui::QmitkContourModelToImageWidgetControls m_Controls;
QFutureWatcher m_Watcher;
};
QmitkContourModelToImageWidgetPrivate::QmitkContourModelToImageWidgetPrivate()
{
}
QmitkContourModelToImageWidgetPrivate::~QmitkContourModelToImageWidgetPrivate()
{
}
void QmitkContourModelToImageWidgetPrivate::EnableButtons(bool enable)
{
m_Controls.btnProcess->setEnabled(enable);
}
void QmitkContourModelToImageWidgetPrivate::SelectionControl(unsigned int index, const mitk::DataNode* /*selection*/)
{
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(index);
dataSelectionWidget->SetHelpText("");
this->EnableButtons();
}
mitk::LabelSetImage::Pointer QmitkContourModelToImageWidgetPrivate::FillContourModelSetIntoImage(mitk::Image* image, mitk::ContourModelSet* contourSet, mitk::TimePointType timePoint)
{
// Use mitk::ContourModelSetToImageFilter to fill the ContourModelSet into the image
mitk::ContourModelSetToImageFilter::Pointer contourFiller = mitk::ContourModelSetToImageFilter::New();
auto timeStep = image->GetTimeGeometry()->TimePointToTimeStep(timePoint);
contourFiller->SetTimeStep(timeStep);
contourFiller->SetImage(image);
contourFiller->SetInput(contourSet);
contourFiller->MakeOutputBinaryOn();
try
{
contourFiller->Update();
}
catch (const std::exception & e)
{
MITK_ERROR << "Error while converting contour model. "<< e.what();
}
catch (...)
{
MITK_ERROR << "Unknown error while converting contour model.";
}
if (nullptr == contourFiller->GetOutput())
{
MITK_ERROR<<"Could not write the selected contours into the image!";
}
auto result = mitk::LabelSetImage::New();
result->InitializeByLabeledImage(contourFiller->GetOutput());
return result;
}
void QmitkContourModelToImageWidget::OnSelectionChanged(unsigned int index, const mitk::DataNode* selection)
{
Q_D(QmitkContourModelToImageWidget);
QmitkDataSelectionWidget* dataSelectionWidget = d->m_Controls.dataSelectionWidget;
mitk::DataNode::Pointer node0 = dataSelectionWidget->GetSelection(0);
mitk::DataNode::Pointer node1 = dataSelectionWidget->GetSelection(1);
if (node0.IsNull() || node1.IsNull() )
{
d->EnableButtons(false);
dataSelectionWidget->SetHelpText(HelpText);
}
else
{
d->SelectionControl(index, selection);
}
}
void QmitkContourModelToImageWidget::OnProcessingFinished()
{
// Called when processing finished
// Adding the result to the data storage
Q_D(QmitkContourModelToImageWidget);
// Adding the result to the data storage
auto result = d->m_Watcher.result();
if (result.IsNotNull())
{
QmitkDataSelectionWidget* dataSelectionWidget = d->m_Controls.dataSelectionWidget;
mitk::DataNode::Pointer imageNode = dataSelectionWidget->GetSelection(0);
mitk::DataNode::Pointer contourNode = dataSelectionWidget->GetSelection(1);
mitk::DataNode::Pointer filled = mitk::DataNode::New();
std::stringstream stream;
stream << imageNode->GetName();
stream << "_";
stream << contourNode->GetName();
filled->SetName(stream.str());
filled->SetData(result);
auto dataStorage = dataSelectionWidget->GetDataStorage();
if (dataStorage.IsNull())
{
std::string exception = "Cannot add result to the data storage. Data storage invalid.";
MITK_ERROR << "Error filling contours into an image: " << exception;
QMessageBox::information(nullptr, "Error filling contours into an image", QString::fromStdString(exception));
}
dataStorage->Add(filled, imageNode);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
else
{
MITK_ERROR<<"Error filling contours into an image!";
}
d->EnableButtons();
}
void QmitkContourModelToImageWidget::OnProcessPressed()
{
Q_D(QmitkContourModelToImageWidget);
QmitkDataSelectionWidget* dataSelectionWidget = d->m_Controls.dataSelectionWidget;
mitk::DataNode::Pointer imageNode = dataSelectionWidget->GetSelection(0);
mitk::DataNode::Pointer contourNode = dataSelectionWidget->GetSelection(1);
// Check if data nodes are valid
if(imageNode.IsNull() || contourNode.IsNull() )
{
MITK_ERROR << "Selection does not contain valid data";
QMessageBox::information( this, "Contour To Image",
"Selection does not contain valid data, please select a binary image and a contour(set)",
QMessageBox::Ok );
d->m_Controls.btnProcess->setEnabled(false);
return;
}
mitk::Image::Pointer image = static_cast(imageNode->GetData());
// Check if the image is valid
if (image.IsNull())
{
MITK_ERROR<<"Error writing contours into image! Invalid image data selected!";
return;
}
const auto timePoint = this->GetTimeNavigationController()->GetSelectedTimePoint();
if (!image->GetTimeGeometry()->IsValidTimePoint(timePoint))
{
MITK_ERROR << "Error writing contours into image! Currently selected time point is not supported by selected image data.";
return;
}
// Check if the selected contours are valid
mitk::ContourModelSet::Pointer contourSet;
mitk::ContourModel::Pointer contour = dynamic_cast(contourNode->GetData());
if (contour.IsNotNull())
{
contourSet = mitk::ContourModelSet::New();
contourSet->AddContourModel(contour);
}
else
{
contourSet = static_cast(contourNode->GetData());
if (contourSet.IsNull())
{
MITK_ERROR<<"Error writing contours into binary image! Invalid contour data selected!";
return;
}
}
//Disable Buttons during calculation and initialize Progressbar
d->EnableButtons(false);
// Start the computation in a background thread
QFuture< mitk::LabelSetImage::Pointer > future = QtConcurrent::run(d, &QmitkContourModelToImageWidgetPrivate::FillContourModelSetIntoImage, image, contourSet, timePoint);
d->m_Watcher.setFuture(future);
}
QmitkContourModelToImageWidget::QmitkContourModelToImageWidget(mitk::DataStorage* dataStorage,
mitk::SliceNavigationController* timeNavigationController,
QWidget* parent)
: QmitkSegmentationUtilityWidget(timeNavigationController, parent),
d_ptr(new QmitkContourModelToImageWidgetPrivate())
{
Q_D(QmitkContourModelToImageWidget);
// Set up UI
d->m_Controls.setupUi(this);
d->m_Controls.dataSelectionWidget->SetDataStorage(dataStorage);
d->m_Controls.dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::ImageAndSegmentationPredicate);
d->m_Controls.dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::ContourModelPredicate);
d->m_Controls.dataSelectionWidget->SetHelpText(HelpText);
d->EnableButtons(false);
// Create connections
connect (d->m_Controls.btnProcess, SIGNAL(pressed()), this, SLOT(OnProcessPressed()));
connect(d->m_Controls.dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)),
this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*)));
connect(&d->m_Watcher, SIGNAL(finished()), this, SLOT(OnProcessingFinished()));
if( d->m_Controls.dataSelectionWidget->GetSelection(0).IsNotNull() &&
d->m_Controls.dataSelectionWidget->GetSelection(1).IsNotNull() )
{
OnSelectionChanged(0, d->m_Controls.dataSelectionWidget->GetSelection(0));
}
}
QmitkContourModelToImageWidget::~QmitkContourModelToImageWidget()
{
}
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.h
index 562d254434..7c56d7e265 100644
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.h
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.h
@@ -1,76 +1,76 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef QmitkContourModelToImageWidget_h
#define QmitkContourModelToImageWidget_h
#include
#include
#include
class QmitkContourModelToImageWidgetPrivate;
namespace mitk
{
class DataNode;
class DataStorage;
class Image;
class ContourModelSet;
class ContourModel;
class Geometry3D;
class PlaneGeometry;
}
/*!
\brief QmitkContourModelToImageWidget
Tool masks an image with a binary image or a surface. The Method requires
an image and a binary image mask or a surface. The input image and the binary
image mask must be of the same size. Masking with a surface creates first a
binary image of the surface and then use this for the masking of the input image.
*/
class MITKSEGMENTATIONUI_EXPORT QmitkContourModelToImageWidget : public QmitkSegmentationUtilityWidget
{
Q_OBJECT
public:
/** @brief Default constructor, including creation of GUI elements and signals/slots connections. */
explicit QmitkContourModelToImageWidget(mitk::DataStorage* dataStorage,
mitk::SliceNavigationController* timeNavigationController,
QWidget* parent = nullptr);
- /** @brief Defaul destructor. */
+ /** @brief Default destructor. */
~QmitkContourModelToImageWidget() override;
private slots:
/** @brief This slot is called if the selection in the workbench is changed. */
void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection);
/** @brief This slot is called if user activates the button to mask an image. */
void OnProcessPressed();
/** @brief This slot is called after processing is finished */
void OnProcessingFinished();
private:
QScopedPointer d_ptr;
Q_DECLARE_PRIVATE(QmitkContourModelToImageWidget)
Q_DISABLE_COPY(QmitkContourModelToImageWidget)
};
#endif
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.h
index b8be1847bf..885ab6aa08 100644
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.h
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.h
@@ -1,87 +1,87 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef QmitkImageMaskingWidget_h
#define QmitkImageMaskingWidget_h
#include
#include
#include
#include
namespace Ui
{
class QmitkImageMaskingWidgetControls;
}
namespace mitk
{
class DataStorage;
class Image;
}
/*!
\brief QmitkImageMaskingWidget
Tool masks an image with a binary image or a surface. The Method requires
an image and a binary image mask or a surface. The input image and the binary
image mask must be of the same size. Masking with a surface creates first a
binary image of the surface and then use this for the masking of the input image.
*/
class MITKSEGMENTATIONUI_EXPORT QmitkImageMaskingWidget : public QmitkSegmentationUtilityWidget
{
Q_OBJECT
public:
/** @brief Default constructor, including creation of GUI elements and signals/slots connections. */
explicit QmitkImageMaskingWidget(mitk::DataStorage* dataStorage,
mitk::SliceNavigationController* timeNavigationController,
QWidget* parent = nullptr);
- /** @brief Defaul destructor. */
+ /** @brief Default destructor. */
~QmitkImageMaskingWidget() override;
private slots:
/** @brief This slot is called if the selection in the workbench is changed. */
void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection);
/** @brief This slot is called if user activates the button to mask an image. */
void OnMaskImagePressed();
/** @brief This slot is called if the user toggles the "Custom" radio button. */
void OnCustomValueButtonToggled(bool checked);
private:
/** @brief Check if selections is valid. */
void SelectionControl( unsigned int index, const mitk::DataNode* selection);
- /** @brief Enable buttons if data selction is valid. */
+ /** @brief Enable buttons if data selection is valid. */
void EnableButtons(bool enable = true);
/** @brief Mask an image with a given binary mask. Note that the input image and the mask image must be of the same size. */
itk::SmartPointer MaskImage(itk::SmartPointer referenceImage, itk::SmartPointer maskImage );
/** @brief Convert a surface into an binary image. */
itk::SmartPointer ConvertSurfaceToImage( itk::SmartPointer image, mitk::Surface::Pointer surface );
/** @brief Adds a new data object to the DataStorage.*/
void AddToDataStorage(mitk::DataStorage::Pointer dataStorage, itk::SmartPointer segmentation,
const std::string& name, mitk::DataNode::Pointer parent = nullptr);
Ui::QmitkImageMaskingWidgetControls* m_Controls;
};
#endif
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.h
index 55e2178163..dcc182211c 100644
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.h
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.h
@@ -1,77 +1,77 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef QmitkSurfaceToImageWidget_h
#define QmitkSurfaceToImageWidget_h
#include
#include
#include "itkSmartPointer.h"
namespace Ui
{
class QmitkSurfaceToImageWidgetControls;
}
namespace mitk
{
class DataNode;
class DataStorage;
class Surface;
class Image;
class LabelSetImage;
}
/*!
\brief QmitkSurfaceToImageWidget
The Tool converts a surface to a binary image. The Method requires
a surface and an image, which header information defines the output
image. The resulting binary image has the same dimension, size, and
Geometry3D as the input image.
*/
class MITKSEGMENTATIONUI_EXPORT QmitkSurfaceToImageWidget : public QmitkSegmentationUtilityWidget
{
Q_OBJECT
public:
/** @brief Default constructor, including creation of GUI elements and signals/slots connections. */
explicit QmitkSurfaceToImageWidget(mitk::DataStorage* dataStorage,
mitk::SliceNavigationController* timeNavigationController,
QWidget* parent = nullptr);
- /** @brief Defaul destructor. */
+ /** @brief Default destructor. */
~QmitkSurfaceToImageWidget() override;
private slots:
/** @brief This slot is called if the selection in the workbench is changed. */
void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection);
/** @brief This slot is called if user activates the button to convert a surface into a binary image. */
void OnSurface2ImagePressed();
private:
- /** @brief Enable buttons if data selction is valid. */
+ /** @brief Enable buttons if data selection is valid. */
void EnableButtons(bool enable = true);
/** @brief Convert a surface into an binary image. */
itk::SmartPointer ConvertSurfaceToImage( itk::SmartPointer image, itk::SmartPointer surface );
Ui::QmitkSurfaceToImageWidgetControls* m_Controls;
};
#endif
diff --git a/Plugins/org.blueberry.core.commands/src/berryCommandEvent.h b/Plugins/org.blueberry.core.commands/src/berryCommandEvent.h
index 2fc3296faa..86348fa8ce 100755
--- a/Plugins/org.blueberry.core.commands/src/berryCommandEvent.h
+++ b/Plugins/org.blueberry.core.commands/src/berryCommandEvent.h
@@ -1,178 +1,178 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef BERRYCOMMANDEVENT_H_
#define BERRYCOMMANDEVENT_H_
#include "common/berryAbstractNamedHandleEvent.h"
#include
namespace berry {
class Command;
/**
* An instance of this class describes changes to an instance of
* Command
.
*
* This class is not intended to be extended by clients.
*
*
* @see ICommandListener#CommandChanged(CommandEvent::Pointer)
*/
class BERRY_COMMANDS CommandEvent : public AbstractNamedHandleEvent {
public:
berryObjectMacro(CommandEvent);
/**
* Creates a new instance of this class.
*
* @param command
* the instance of the interface that changed.
* @param categoryChanged
* true
, iff the category property changed.
* @param definedChanged
* true
, iff the defined property changed.
* @param descriptionChanged
* true
, iff the description property changed.
* @param handledChanged
* true
, iff the handled property changed.
* @param nameChanged
* true
, iff the name property changed.
* @param parametersChanged
* true
if the parameters have changed;
* false
otherwise.
* @param returnTypeChanged
* true
iff the return type property changed;
* false
otherwise.
* @param helpContextIdChanged
* true
iff the help context identifier changed;
* false
otherwise.
* @param enabledChanged
- * true
iff the comand enablement changed;
+ * true
iff the command enablement changed;
* false
otherwise.
* @since 3.3
*/
CommandEvent(const SmartPointer command, bool categoryChanged,
bool definedChanged, bool descriptionChanged,
bool handledChanged, bool nameChanged,
bool parametersChanged, bool returnTypeChanged = false,
bool helpContextIdChanged = false, bool enabledChanged = false);
/**
* Returns the instance of the interface that changed.
*
* @return the instance of the interface that changed. Guaranteed not to be
* null
.
*/
SmartPointer GetCommand() const;
/**
* Returns whether or not the category property changed.
*
* @return true
, iff the category property changed.
*/
bool IsCategoryChanged() const;
/**
* Returns whether or not the handled property changed.
*
* @return true
, iff the handled property changed.
*/
bool IsHandledChanged() const;
/**
* Returns whether or not the help context identifier changed.
*
* @return true
, iff the help context identifier changed.
* @since 3.2
*/
bool IsHelpContextIdChanged() const;
/**
* Returns whether or not the parameters have changed.
*
* @return true
, iff the parameters property changed.
*/
bool IsParametersChanged() const;
/**
* Returns whether or not the return type property changed.
*
* @return true
, iff the return type property changed.
* @since 3.2
*/
bool IsReturnTypeChanged() const;
/**
* Return whether the enable property changed.
*
- * @return true
iff the comand enablement changed
+ * @return true
iff the command enablement changed
* @since 3.3
*/
bool IsEnabledChanged() const;
private:
/**
* The bit used to represent whether the command has changed its category.
*/
static int CHANGED_CATEGORY(); // = LAST_USED_BIT << 1;
/**
* The bit used to represent whether the command has changed its handler.
*/
static int CHANGED_HANDLED(); // = LAST_USED_BIT << 2;
/**
* The bit used to represent whether the command has changed its parameters.
*/
static int CHANGED_PARAMETERS(); // = LAST_USED_BIT << 3;
/**
* The bit used to represent whether the command has changed its return
* type.
*
* @since 3.2
*/
static int CHANGED_RETURN_TYPE(); // = LAST_USED_BIT << 4;
/**
* The bit used to represent whether the command has changed its help
* context identifier.
*
* @since 3.2
*/
static int CHANGED_HELP_CONTEXT_ID(); // = LAST_USED_BIT << 5;
/**
* The bit used to represent whether this commands active handler has
* changed its enablement state.
*
* @since 3.3
*/
static int CHANGED_ENABLED(); // = LAST_USED_BIT << 6;
/**
* The command that has changed; this value is never null
.
*/
const SmartPointer command;
};
}
#endif /* BERRYCOMMANDEVENT_H_ */
diff --git a/Plugins/org.blueberry.core.commands/src/berryIParameterValueConverter.h b/Plugins/org.blueberry.core.commands/src/berryIParameterValueConverter.h
index 487a0f66ee..f1139aeef0 100755
--- a/Plugins/org.blueberry.core.commands/src/berryIParameterValueConverter.h
+++ b/Plugins/org.blueberry.core.commands/src/berryIParameterValueConverter.h
@@ -1,89 +1,89 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef BERRYABSTRACTPARAMETERVALUECONVERTER_H_
#define BERRYABSTRACTPARAMETERVALUECONVERTER_H_
#include
#include
#include
namespace berry {
/**
*
* Supports conversion between objects and strings for command parameter values.
* Extenders must produce strings that identify objects (of a specific command
* parameter type) as well as consume the strings to locate and return the
* objects they identify.
*
*
* This class offers multiple handlers of a command a consistent way of
* converting string parameter values into the objects that the handlers would
* prefer to deal with. This class also gives clients a way to serialize
* object parameters as strings so that entire parameterized commands can be
* serialized, stored and later deserialized and executed.
*
*
* This class will typically be extended so the subclass can be referenced from
* the converter
attribute of the
- * commandParameterType
elemement of the
+ * commandParameterType
element of the
* org.blueberry.ui.commands
extension-point. Objects implementing
* this interface may also be passed directly to
* {@link ParameterType#Define} by clients.
*
*
* @see ParameterType#Define(IParameterValueConverter::Pointer)
* @see ParameterizedCommand#Serialize()
*/
struct BERRY_COMMANDS IParameterValueConverter {
virtual ~IParameterValueConverter();
/**
* Converts a string encoded command parameter value into the parameter
* value object.
*
* @param parameterValue
* a command parameter value string describing an object; may be
* null
* @return the object described by the command parameter value string; may
* be null
* @throws ParameterValueConversionException
* if an object cannot be produced from the
* parameterValue
string
*/
virtual Object::Pointer ConvertToObject(const QString& parameterValue) = 0;
/**
* Converts a command parameter value object into a string that encodes a
* reference to the object or serialization of the object.
*
* @param parameterValue
* an object to convert into an identifying string; may be
* null
* @return a string describing the provided object; may be null
* @throws ParameterValueConversionException
* if a string reference or serialization cannot be provided for
* the parameterValue
*/
virtual QString ConvertToString(const Object::Pointer& parameterValue) = 0;
};
}
Q_DECLARE_INTERFACE(berry::IParameterValueConverter, "org.blueberry.core.commands.IParameterValueConverter")
#endif /* BERRYABSTRACTPARAMETERVALUECONVERTER_H_ */
diff --git a/Plugins/org.blueberry.core.commands/src/common/berryCommandExceptions.h b/Plugins/org.blueberry.core.commands/src/common/berryCommandExceptions.h
index a0bbaf6124..e0523ac0b5 100644
--- a/Plugins/org.blueberry.core.commands/src/common/berryCommandExceptions.h
+++ b/Plugins/org.blueberry.core.commands/src/common/berryCommandExceptions.h
@@ -1,53 +1,53 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef BERRYCOMMANDEXCEPTIONS_H_
#define BERRYCOMMANDEXCEPTIONS_H_
#include
#include
namespace berry {
CTK_DECLARE_EXCEPTION(BERRY_COMMANDS, CommandException, ctkRuntimeException)
CTK_DECLARE_EXCEPTION(BERRY_COMMANDS, ExecutionException, CommandException)
CTK_DECLARE_EXCEPTION(BERRY_COMMANDS, NotHandledException, CommandException)
CTK_DECLARE_EXCEPTION(BERRY_COMMANDS, NotDefinedException, CommandException)
CTK_DECLARE_EXCEPTION(BERRY_COMMANDS, NotEnabledException, CommandException)
CTK_DECLARE_EXCEPTION(BERRY_COMMANDS, ParameterValueConversionException, CommandException)
/**
* Signals that a problem has occurred while trying to create an instance of
* IParameterValues
. In applications based on the registry
* provided by core, this usually indicates a problem creating an
* IExecutableExtension
. For other applications, this exception
* could be used to signify any general problem during initialization.
*
*/
CTK_DECLARE_EXCEPTION(BERRY_COMMANDS, ParameterValuesException, CommandException)
/**
- * Signals that an exception occured while serializing a
+ * Signals that an exception occurred while serializing a
* {@link ParameterizedCommand} to a string or deserializing a string to a
* {@link ParameterizedCommand}.
*
* This class is not intended to be extended by clients.
*
*/
CTK_DECLARE_EXCEPTION(BERRY_COMMANDS, SerializationException, CommandException)
}
#endif /*BERRYCOMMANDEXCEPTIONS_H_*/
diff --git a/Plugins/org.blueberry.core.expressions/plugin.xml b/Plugins/org.blueberry.core.expressions/plugin.xml
index 3509a3e70b..ed9cf70941 100644
--- a/Plugins/org.blueberry.core.expressions/plugin.xml
+++ b/Plugins/org.blueberry.core.expressions/plugin.xml
@@ -1,18 +1,18 @@
-
+
diff --git a/Plugins/org.blueberry.core.expressions/src/berryPropertyTester.h b/Plugins/org.blueberry.core.expressions/src/berryPropertyTester.h
index ca5b531d59..aef7eeadf8 100644
--- a/Plugins/org.blueberry.core.expressions/src/berryPropertyTester.h
+++ b/Plugins/org.blueberry.core.expressions/src/berryPropertyTester.h
@@ -1,121 +1,121 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef BERRYPROPERTYTESTER_H_
#define BERRYPROPERTYTESTER_H_
#include
#include "internal/berryPropertyTesterDescriptor.h"
#include
namespace berry {
/**
* Abstract superclass of all property testers. Implementation classes of
- * the extension point org.blueberry.core.expresssions.propertyTesters
+ * the extension point org.blueberry.core.expressions.propertyTesters
*
must extend PropertyTester
.
*
* A property tester implements the property tests enumerated in the property
* tester extension point. For the following property test extension
* \code{.unparsed}
*
*
* \endcode
* the corresponding implementation class looks like:
* \code
* public class MyPackageFragmentTester {
* public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
* IPackageFragment fragement= (IPackageFragment)receiver;
* if ("isDefaultPackage".equals(property)) {
* return expectedValue == null
* ? fragement.isDefaultPackage()
* : fragement.isDefaultPackage() == ((Boolean)expectedValue).booleanValue();
* }
* Assert.isTrue(false);
* return false;
* }
* }
* \endcode
* The property can then be used in a test expression as follows:
*
* <instanceof value="org.blueberry.core.IPackageFragment"/>
* <test property="org.blueberry.jdt.core.isDefaultPackage"/>
*
*
*
* There is no guarantee that the same instance of a property tester is used
* to handle <test property="..."/> requests. So property testers
* should always be implemented in a stateless fashion.
*
*/
class BERRY_EXPRESSIONS PropertyTester : public QObject, public IPropertyTester
{
Q_OBJECT
Q_INTERFACES(berry::IPropertyTester)
private:
IConfigurationElement::Pointer fConfigElement;
QString fNamespace;
QString fProperties;
public:
/**
* Initialize the property tester with the given name space and property.
*
* Note: this method is for internal use only. Clients must not call
* this method.
*
* @param descriptor the descriptor object for this tester
*/
void InternalInitialize(PropertyTesterDescriptor::Pointer descriptor);
/**
* Note: this method is for internal use only. Clients must not call
* this method.
*
* @return the property tester descriptor
*/
PropertyTesterDescriptor::Pointer InternalCreateDescriptor();
/**
* {@inheritDoc}
*/
bool Handles(const QString& namespaze, const QString& property) override;
/**
* {@inheritDoc}
*/
bool IsInstantiated() override;
/**
* {@inheritDoc}
*/
bool IsDeclaringPluginActive() override;
/**
* {@inheritDoc}
*/
IPropertyTester* Instantiate() override;
};
} // namespace berry
#endif /*BERRYPROPERTYTESTER_H_*/
diff --git a/Plugins/org.blueberry.core.expressions/src/internal/berryTypeExtensionManager.h b/Plugins/org.blueberry.core.expressions/src/internal/berryTypeExtensionManager.h
index aeace05b79..580fdc1752 100644
--- a/Plugins/org.blueberry.core.expressions/src/internal/berryTypeExtensionManager.h
+++ b/Plugins/org.blueberry.core.expressions/src/internal/berryTypeExtensionManager.h
@@ -1,123 +1,123 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef BERRYTYPEEXTENSIONMANAGER_H_
#define BERRYTYPEEXTENSIONMANAGER_H_
#include "berryIPropertyTester.h"
#include "berryTypeExtension.h"
#include "berryPropertyCache.h"
#include "berryProperty.h"
#include
#include
#include
#include
namespace berry {
class TypeExtensionManager : private IRegistryEventListener
{
private:
QString fExtensionPoint;
static const QString TYPE;
class nullptr_PROPERTY_TESTER_ : public IPropertyTester
{
public:
bool Handles(const QString& /*namespaze*/, const QString& /*property*/) override
{
return false;
}
bool IsInstantiated() override
{
return true;
}
bool IsDeclaringPluginActive() override
{
return true;
}
IPropertyTester* Instantiate() override
{
return this;
}
bool Test(Object::ConstPointer, const QString& /*property*/,
const QList& /*args*/, Object::Pointer /*expectedValue*/) override
{
return false;
}
};
static const nullptr_PROPERTY_TESTER_ nullptr_PROPERTY_TESTER;
/*
* Map containing all already created type extension object.
*/
QHash fTypeExtensionMap;
/*
* Table containing mapping of class name to configuration element
*/
QHash > fConfigurationElementMap;
/*
* A cache to give fast access to the last 1000 method invocations.
*/
PropertyCache* fPropertyCache;
public:
static bool DEBUG;
TypeExtensionManager(const QString& extensionPoint);
~TypeExtensionManager() override;
Property::Pointer GetProperty(Object::ConstPointer receiver,
const QString& namespaze, const QString& method);
/*synchronized*/Property::Pointer GetProperty(Object::ConstPointer receiver,
const QString& namespaze, const QString& method, bool forcePluginActivation);
protected:
friend class TypeExtension;
/*
* This method doesn't need to be synchronized since it is called
- * from withing the getProperty method which is synchronized
+ * from within the getProperty method which is synchronized
*/
TypeExtension::Pointer Get(const Reflection::TypeInfo& typeInfo);
/*
* This method doesn't need to be synchronized since it is called
- * from withing the getProperty method which is synchronized
+ * from within the getProperty method which is synchronized
*/
QList LoadTesters(const QString& typeName);
private:
/*synchronized*/void InitializeCaches();
void Added(const QList >& extensions) override;
void Removed(const QList >& extensions) override;
void Added(const QList >& extensionPoints) override;
void Removed(const QList >& extensionPoints) override;
};
}
#endif /*BERRYTYPEEXTENSIONMANAGER_H_*/
diff --git a/Plugins/org.blueberry.core.jobs/src/berryIJobChangeListener.h b/Plugins/org.blueberry.core.jobs/src/berryIJobChangeListener.h
index 1d8e41422f..bd400e9ba1 100644
--- a/Plugins/org.blueberry.core.jobs/src/berryIJobChangeListener.h
+++ b/Plugins/org.blueberry.core.jobs/src/berryIJobChangeListener.h
@@ -1,140 +1,140 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef BERRYIJOBCHANGELISTENER_H_
#define BERRYIJOBCHANGELISTENER_H_
#include "berryIJobChangeEvent.h"
namespace berry
{
/**
* Callback interface for clients interested in being notified when jobs change state.
*
* A single job listener instance can be added either to the job manager, for notification
* of all scheduled jobs, or to any set of individual jobs. A single listener instance should
* not be added to both the job manager, and to individual jobs (such a listener may
* receive duplicate notifications).
*
* Clients should not rely on the result of the Job#GetState()
* method on jobs for which notification is occurring. Listeners are notified of
* all job state changes, but whether the state change occurs before, during, or
* after listeners are notified is unspecified.
*
* Clients may implement this interface.
*
* @see IJobManager#AddJobChangeListener(IJobChangeListener::Pointer)
* @see IJobManager#RemoveJobChangeListener(IJobChangeListener::Pointer)
* @see Job#AddJobChangeListener(IJobChangeListener::Pointer)
* @see Job#GetState()
* @see Job#RemoveJobChangeListener(IJobChangeListener::Pointer)
*/
struct BERRY_JOBS IJobChangeListener
{
struct BERRY_JOBS Events
{
typedef Message1 JobChangeEventType;
enum Type
{
NONE = 0x00000000,
ABOUT_TO_RUN = 0x00000001,
AWAKE = 0x00000002,
DONE = 0x00000004,
RUNNING = 0x00000008,
SCHEDULED = 0x00000010,
SLEEPING = 0x00000020,
ALL = 0xffffffff
};
Q_DECLARE_FLAGS(Types, Type)
JobChangeEventType jobAboutToRun;
JobChangeEventType jobAwake;
JobChangeEventType jobDone;
JobChangeEventType jobRunning;
JobChangeEventType jobScheduled;
JobChangeEventType jobSleeping;
void AddListener(IJobChangeListener* listener);
void RemoveListener(IJobChangeListener* listener);
void SetExceptionHandler(const AbstractExceptionHandler& handler);
typedef MessageDelegate1
Delegate;
};
virtual Events::Types GetEventTypes() = 0;
/**
* Notification that a job is about to be run. Listeners are allowed to sleep, cancel,
* or change the priority of the job before it is started (and as a result may prevent
* the run from actually occurring).
*/
virtual void AboutToRun(const IJobChangeEvent::ConstPointer& /*event*/)
{
}
/**
* Notification that a job was previously sleeping and has now been rescheduled
* to run.
*/
virtual void Awake(const IJobChangeEvent::ConstPointer& /*event*/)
{
}
/**
- * Notification that a job has completed execution, either due to cancelation, successful
+ * Notification that a job has completed execution, either due to cancellation, successful
* completion, or failure. The event status object indicates how the job finished,
* and the reason for failure, if applicable.
*/
virtual void Done(const IJobChangeEvent::ConstPointer& /*event*/)
{
}
/**
* Notification that a job has started running.
*/
virtual void Running(const IJobChangeEvent::ConstPointer& /*event*/)
{
}
/**
* Notification that a job is being added to the queue of scheduled jobs.
* The event details includes the scheduling delay before the job should start
* running.
*/
virtual void Scheduled(const IJobChangeEvent::ConstPointer& /*event*/)
{
}
/**
* Notification that a job was waiting to run and has now been put in the
* sleeping state.
*/
virtual void Sleeping(const IJobChangeEvent::ConstPointer& /*event*/)
{
}
};
}
Q_DECLARE_OPERATORS_FOR_FLAGS(berry::IJobChangeListener::Events::Types)
#endif /* BERRYIJOBCHANGELISTENER_H_ */
diff --git a/Plugins/org.blueberry.core.jobs/src/internal/berryJobManager.cpp b/Plugins/org.blueberry.core.jobs/src/internal/berryJobManager.cpp
index 7bb26f7cfc..43fda5b558 100644
--- a/Plugins/org.blueberry.core.jobs/src/internal/berryJobManager.cpp
+++ b/Plugins/org.blueberry.core.jobs/src/internal/berryJobManager.cpp
@@ -1,1202 +1,1202 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#define NOMINMAX
#include "berryJobManager.h"
#include "berryIProgressMonitor.h"
#include "berryNullProgressMonitor.h"
#include "berryIStatus.h"
#include "berryJobStatus.h"
#include
#include
namespace berry
{
/**
* test class implementing ISchedulingRule to validate client defined rules
*/
struct NullRule: public ISchedulingRule
{
bool Contains(ISchedulingRule::Pointer myRule) const override;
bool IsConflicting(ISchedulingRule::Pointer myRule) const override;
};
bool NullRule::IsConflicting(ISchedulingRule::Pointer dummyRule) const
{
return dummyRule == this;
}
bool NullRule::Contains(ISchedulingRule::Pointer dummyRule) const
{
return dummyRule == this;
}
JobManager::JobManager() :
sptr_testRule(new NullRule()),m_active(true), m_Pool(new WorkerPool(this)), m_sptr_progressProvider(nullptr),
m_JobQueueSleeping(true), m_JobQueueWaiting(false),m_suspended(false), m_waitQueueCounter(0)
{
m_JobListeners.global.SetExceptionHandler(MessageExceptionHandler<
JobListeners> (&m_JobListeners, &JobListeners::HandleException));
}
// DEBUG VARIABLES
const QString& JobManager::PI_JOBS()
{
static const QString id("org.blueberry.core.jobs");
return id;
}
bool JobManager::DEBUG = false;
bool JobManager::DEBUG_BEGIN_END = false;
bool JobManager::DEBUG_DEADLOCK = false;
bool JobManager::DEBUG_LOCKS = false;
bool JobManager::DEBUG_TIMING = false;
bool JobManager::DEBUG_SHUTDOWN = false;
const int JobManager::PLUGIN_ERROR = 2;
JobManager*
JobManager::GetInstance()
{
// we don't need to lock the creation of "instance" because GetInstance() is
// called when statically initializing InternalJob::ptr_manager (which happens
// in single-threaded mode)
static JobManager instance;
return &instance;
}
std::string JobManager::PrintState(int state)
{
switch (state)
{
case Job::NONE:
return "NONE";
case Job::WAITING:
return "WAITING";
case Job::SLEEPING:
return "SLEEPING";
case Job::RUNNING:
return "RUNNING";
case InternalJob::BLOCKED:
return "BLOCKED";
case InternalJob::ABOUT_TO_RUN:
return "ABOUT_TO_RUN";
case InternalJob::ABOUT_TO_SCHEDULE:
return "ABOUT_TO_SCHEDULE";
}
return "UNKNOWN";
}
void JobManager::Shutdown()
{
JobManager* ptr_instance(GetInstance());
if (ptr_instance != nullptr)
{
ptr_instance->DoShutdown();
// ptr_instance = 0; // need to call the destructor of the static object ..
}
}
//void
//JobManager
//::Cancel(Object family) {
// //don't synchronize because cancel calls listeners
// for (Iterator it = select(family).iterator(); it.hasNext();)
// cancel((Job) it.next());
// }
IProgressMonitor::Pointer JobManager::CreateProgressGroup()
{
if (m_sptr_progressProvider != 0)
return (m_sptr_progressProvider->CreateProgressGroup());
NullProgressMonitor::Pointer sptr_defaultProgressMonitor(
new NullProgressMonitor);
return sptr_defaultProgressMonitor;
}
Job*
JobManager::CurrentJob()
{
//Poco::Thread* ptr_current = Poco::Thread::current();
//if (Worker* worker = dynamic_cast(ptr_current) )
// return ((Worker) ptr_current).currentJob();
// {
// Poco::ScopedLock lockMe (m_mutex);
// Poco::HashSet::Iterator it ;
// for (it = m_running.begin(); it != m_running.end(); it ++) {
// Job job* = dynamic_cast (it);
// if (job->GetThread() == ptr_current)
// return job;
// }
//}
return nullptr;
}
//void
//JobManager
//::EndRule(ISchedulingRule rule) {
//implicitJobs.end(rule, false);
// }
//Job[]
//JobManager
//::Find(Object family) {
// List members = select(family);
// return (Job[]) members.toArray(new Job[members.size()]);
// }
//
// LockManager GetLockManager() {
// return lockManager;
// }
//
bool JobManager::IsIdle()
{
{
Poco::ScopedLock m_managerLock(m_mutex);
return m_running.empty() && m_JobQueueWaiting.IsEmpty();
}
}
bool JobManager::IsSuspended()
{
{
Poco::ScopedLock m_managerLock(m_mutex);
m_suspended = true;
}
return m_suspended;
}
//
// /*
// * @see IJobManager#join(String, IProgressMonitor)
// */
//void
//JobManager
//::Join(final Object family, IProgressMonitor monitor) throws InterruptedException, OperationCanceledException {
// monitor = monitorFor(monitor);
// IJobChangeListener listener = null;
// final Set jobs;
// int jobCount;
// Job blocking = null;
// synchronized (lock) {
// //don't join a waiting or sleeping job when suspended (deadlock risk)
// int states = suspended ? Job.RUNNING : Job.RUNNING | Job.WAITING | Job.SLEEPING;
// jobs = Collections.synchronizedSet(new HashSet(select(family, states)));
// jobCount = jobs.size();
// if (jobCount > 0) {
// //if there is only one blocking job, use it in the blockage callback below
// if (jobCount == 1)
// blocking = (Job) jobs.iterator().next();
// listener = new JobChangeAdapter() {
// public void done(IJobChangeEvent event) {
// //don't remove from list if job is being rescheduled
// if (!((JobChangeEvent) event).reschedule)
// jobs.remove(event.getJob());
// }
//
// //update the list of jobs if new ones are added during the join
// public void scheduled(IJobChangeEvent event) {
// //don't add to list if job is being rescheduled
// if (((JobChangeEvent) event).reschedule)
// return;
// Job job = event.getJob();
// if (job.belongsTo(family))
// jobs.add(job);
// }
// };
// addJobChangeListener(listener);
// }
// }
// if (jobCount == 0) {
// //use up the monitor outside synchronized block because monitors call untrusted code
// monitor.beginTask(JobMessages.jobs_blocked0, 1);
// monitor.done();
// return;
// }
// //spin until all jobs are completed
// try {
// monitor.beginTask(JobMessages.jobs_blocked0, jobCount);
// monitor.subTask(NLS.bind(JobMessages.jobs_waitFamSub, Integer.toString(jobCount)));
// reportBlocked(monitor, blocking);
// int jobsLeft;
// int reportedWorkDone = 0;
// while ((jobsLeft = jobs.size()) > 0) {
// //don't let there be negative work done if new jobs have
// //been added since the join began
// int actualWorkDone = Math.max(0, jobCount - jobsLeft);
// if (reportedWorkDone < actualWorkDone) {
// monitor.worked(actualWorkDone - reportedWorkDone);
// reportedWorkDone = actualWorkDone;
// monitor.subTask(NLS.bind(JobMessages.jobs_waitFamSub, Integer.toString(jobsLeft)));
// }
// if (Thread.interrupted())
// throw new InterruptedException();
// if (monitor.isCanceled())
// throw new OperationCanceledException();
// //notify hook to service pending syncExecs before falling asleep
// lockManager.aboutToWait(null);
// Thread.sleep(100);
// }
// } finally {
// lockManager.aboutToRelease();
// removeJobChangeListener(listener);
// reportUnblocked(monitor);
// monitor.done();
// }
// }
//JobManager
//::NewLock() {
// return lockManager.newLock();
// }
void JobManager::RemoveJobChangeListener(IJobChangeListener* listener)
{
m_JobListeners.Remove(listener);
}
void JobManager::ReportBlocked(IProgressMonitor::Pointer sptr_monitor, InternalJob::Pointer sptr_blockingJob) const
{
if ( sptr_monitor.Cast() == 0 )
return ;
if (sptr_blockingJob == 0 || sptr_blockingJob->IsSystem())
{
Status::Pointer sptr_reason(
new Status(IStatus::INFO_TYPE, JobManager::PI_JOBS(), 1,
"the user operation is waiting for background work to complete",
BERRY_STATUS_LOC));
}
else
{
QString msg = "the user operation is waiting for : " + sptr_blockingJob->GetName() +
" to complete. ";
JobStatus::Pointer sptr_reason(
new JobStatus(IStatus::INFO_TYPE, sptr_blockingJob.Cast(), msg,
BERRY_STATUS_LOC));
}
// ((IProgressmonitorWithBlocking) sptr_monitor)->SetBlocked(sptr_reason);
}
void JobManager::ReportUnblocked(IProgressMonitor::Pointer sptr_monitor) const
{
if ( IProgressMonitorWithBlocking::Pointer sptr_monitorWithBlocking = sptr_monitor.Cast() )
sptr_monitorWithBlocking->ClearBlocked();
}
void JobManager::Resume()
{
{
Poco::ScopedLock lockMe(m_mutex);
m_suspended = false;
//poke the job pool
m_Pool->JobQueued();
}
}
//TODO implicit Jobs
//void
//JobManager
//::Resume(ISchedulingRule rule)const {
// implicitJobs.resume(rule);
// }
void JobManager::SetProgressProvider(ProgressProvider::Pointer provider)
{
m_sptr_progressProvider = provider;
}
void JobManager::SetRule(InternalJob::Pointer job,
ISchedulingRule::Pointer sptr_rule)
{
Poco::ScopedLock m_managerLock(m_mutex);
//cannot change the rule of a job that is already running ( GetRule is set to protected which should be
// changed if this assert is needed
// assert(job->GetState() == Job.NONE);
ValidateRule(sptr_rule);
job->InternalSetRule(sptr_rule);
}
//void
//JobManager
//::Sleep(Object family) {
// //don't synchronize because sleep calls listeners
// for (Iterator it = select(family).iterator(); it.hasNext();) {
// sleep((InternalJob) it.next());
// }
// }
void JobManager::Suspend()
{
{
Poco::ScopedLock lockMe(m_mutex);
m_suspended = true;
}
}
//void
//JobManager
//::Suspend(ISchedulingRule rule, IProgressMonitor monitor)const {
// Assert.isNotNull(rule);
// implicitJobs.suspend(rule, monitorFor(monitor));
// }
//void
//JobManager
//::TransferRule(ISchedulingRule rule, Thread destinationThread) {
// implicitJobs.transfer(rule, destinationThread);
// }
//void
//JobManager
//::SetLockListener(LockListener listener) {
// lockManager.setLockListener(listener);
// }
//void
//JobManager
//::WakeUp(Object family) {
// //don't synchronize because wakeUp calls listeners
// for (Iterator it = select(family).iterator(); it.hasNext();) {
// wakeUp((InternalJob) it.next(), 0L);
// }
// }
void JobManager::AddJobChangeListener(IJobChangeListener* listener)
{
m_JobListeners.Add(listener);
}
//void
//JobManager
//::BeginRule(ISchedulingRule rule, IProgressMonitor monitor) {
// validateRule(rule);
// implicitJobs.begin(rule, monitorFor(monitor), false);
// }
//
// /**
// * For debugging purposes only
// */
//std::String
//JobManager
//::PrintJobName(Job job) {
// if (job instanceof ThreadJob) {
// Job realJob = ((ThreadJob) job).realJob;
// if (realJob != null)
// return realJob.getClass().getName();
// return "ThreadJob on rule: " + job.getRule(); //$NON-NLS-1$
// }
// return job.getClass().getName();
// }
//
// instance = this;
// initDebugOptions();
// synchronized (lock) {
// running = new HashSet(10);
// }
// pool.setDaemon(JobOSGiUtils.getDefault().useDaemonThreads());
//}
void JobManager::ChangeState(InternalJob::Pointer sptr_job, int newState)
{
bool blockedJobs = false;
{
Poco::ScopedLock m_managerLock(m_mutex);
int tmp_oldState = sptr_job->InternalGetState();
switch (tmp_oldState)
{
case Job::NONE:
case InternalJob::ABOUT_TO_SCHEDULE:
break;
case InternalJob::BLOCKED:
//remove this job from the linked list of blocked jobs
sptr_job->Remove();
break;
case Job::WAITING:
m_JobQueueWaiting.Remove(sptr_job);
// assert(false, "Tried to remove a job that wasn't in the queue");
break;
case Job::SLEEPING:
m_JobQueueSleeping.Remove(sptr_job);
// assert(false, "Tried to remove a job that wasn't in the queue");
// this silences the warning but should be checked:
// FALLTHRU
case Job::RUNNING:
case InternalJob::ABOUT_TO_RUN:
m_running.remove(sptr_job);
//add any blocked jobs back to the wait queue
InternalJob::Pointer sptr_blocked(sptr_job->Previous());
sptr_job->Remove();
blockedJobs = sptr_blocked != 0;
while (sptr_blocked != 0)
{
InternalJob::Pointer previous = sptr_blocked->Previous();
ChangeState(sptr_blocked, Job::WAITING);
sptr_blocked = previous;
}
break;
// default :
// Assert.isLegal(false, "Invalid job state: " + job + ", state: " + oldState);
}
sptr_job->InternalSetState(newState);
switch (newState)
{
case Job::NONE:
sptr_job->SetStartTime(InternalJob::T_NONE);
sptr_job->SetWaitQueueStamp(InternalJob::T_NONE);
case InternalJob::BLOCKED:
break;
case Job::WAITING:
m_JobQueueWaiting.Enqueue(sptr_job);
break;
case Job::SLEEPING:
//try {
m_JobQueueSleeping.Enqueue(sptr_job);
//} catch (RuntimeException e) {
// throw new RuntimeException("Error changing from state: " + oldState);
//}
break;
case Job::RUNNING:
case InternalJob::ABOUT_TO_RUN:
sptr_job->SetStartTime(InternalJob::T_NONE);
sptr_job->SetWaitQueueStamp(InternalJob::T_NONE);
m_running.insert(sptr_job);
break;
case InternalJob::ABOUT_TO_SCHEDULE:
break;
// default :
// Assert.isLegal(false, "Invalid job state: " + job + ", state: " + newState);
}
}
//notify queue outside sync block
if (blockedJobs)
m_Pool->JobQueued();
}
Poco::Timestamp::TimeDiff JobManager::DelayFor(int priority)
{
//these values may need to be tweaked based on machine speed
switch (priority)
{
case Job::INTERACTIVE:
return 0;
case Job::SHORT:
return 50;
case Job::LONG:
return 100;
case Job::BUILD:
return 500;
case Job::DECORATE:
return 1000;
default:
// Assert.isTrue(false, "Job has invalid priority: " + priority); //$NON-NLS-1$
return 0;
}
}
void JobManager::DoSchedule(InternalJob::Pointer job,
Poco::Timestamp::TimeDiff delay)
{
Poco::ScopedLock managerLock(m_mutex);
//job may have been canceled already
int state = job->InternalGetState();
if (state != InternalJob::ABOUT_TO_SCHEDULE && state != Job::SLEEPING)
return;
//if it's a decoration job with no rule, don't run it right now if the system is busy
if (job->GetPriority() == Job::DECORATE && job->GetRule() == 0)
{
Poco::Timestamp::TimeDiff tmp_minDelay = m_running.size() * 100;
delay = std::max(delay, tmp_minDelay);
}
if (delay > 0)
{
job->SetStartTime(Poco::Timestamp() + delay * 100);
InternalJob::Pointer sptr_job(job);
ChangeState(sptr_job, Job::SLEEPING);
}
else
{
job->SetStartTime(Poco::Timestamp() + DelayFor(job->GetPriority()) * 100);
job->SetWaitQueueStamp(m_waitQueueCounter++);
InternalJob::Pointer sptr_job(job);
ChangeState(sptr_job, Job::WAITING);
}
}
void JobManager::DoShutdown()
{
std::vector vec_ToCancel;
{
Poco::ScopedLock LockMe(m_mutex);
if (m_active)
{
m_active = false;
//cancel all running jobs
vec_ToCancel.assign(m_running.begin(), m_running.end());
//clean up
m_JobQueueSleeping.Clear();
m_JobQueueWaiting.Clear();
m_running.clear();
}
}
// Give running jobs a chance to finish. Wait 0.1 seconds for up to 3 times.
if (!vec_ToCancel.empty())
{
for (std::size_t i = 0; i < vec_ToCancel.size(); i++)
{
// cancel jobs outside sync block to avoid deadlock
Cancel(vec_ToCancel[i]);
}
for (int waitAttempts = 0; waitAttempts < 3; waitAttempts++)
{
Poco::Thread::yield();
{
Poco::ScopedLock LockMe(m_mutex);
if (m_running.empty())
break;
}
if (DEBUG_SHUTDOWN)
{
// JobManager.debug("Shutdown - job wait cycle #" + (waitAttempts + 1));
std::vector vec_StillRunning;
{
Poco::ScopedLock LockMe(m_mutex);
vec_StillRunning.assign(m_running.begin(), m_running.end());
// if (!vec_StillRunning.empty()) {
//for (int j = 0; j < stillRunning.length; j++) {
// JobManager.debug("\tJob: " + printJobName(stillRunning[j])); //$NON-NLS-1$
//}
}
}
Poco::Thread::sleep(100);
Poco::Thread::yield();
}
// retrieve list of the jobs that are still running
{
Poco::ScopedLock LockMe(m_mutex);
vec_ToCancel.assign(m_running.begin(), m_running.end());
}
}
if (!vec_ToCancel.empty())
{
/*for (int i = 0; i < vec_ToCancel.size(); i++) {*/
// std::string tmp_jobName = PrintJobName(toCancel[i]);
// //this doesn't need to be translated because it's just being logged
// String msg = "Job found still running after platform shutdown. Jobs should be canceled by the plugin that
// scheduled them during shutdown: " + jobName;
// RuntimeLog.log(new Status(IStatus.WARNING, JobManager.PI_JOBS, JobManager.PLUGIN_ERROR, msg, null));
//
// // TODO the RuntimeLog.log in its current implementation won't produce a log
// // during this stage of shutdown. For now add a standard error output.
// // One the logging story is improved, the System.err output below can be removed:
// System.err.println(msg);
// }
}
m_Pool->Shutdown();
}
Job::Pointer JobManager::NextJob()
{
{
Poco::ScopedLock managerLock(m_mutex);
//do nothing if the job manager is suspended
if (m_suspended)
return Job::Pointer(nullptr);
// tickle the sleep queue to see if anyone wakes up
Poco::Timestamp now;
InternalJob::Pointer ptr_job = m_JobQueueSleeping.Peek();
while (ptr_job != 0 && ptr_job->GetStartTime() < now)
{
// a job that slept to long is set a new start time and is put into the waiting queue
ptr_job->SetStartTime(now + DelayFor(ptr_job->GetPriority()));
ptr_job->SetWaitQueueStamp(m_waitQueueCounter++);
InternalJob::Pointer sptr_job(ptr_job);
ChangeState(sptr_job, Job::WAITING);
ptr_job = m_JobQueueSleeping.Peek();
}
//process the wait queue until we find a job whose rules are satisfied.
while ((ptr_job = m_JobQueueWaiting.Peek()) != 0)
{
InternalJob::Pointer sptr_job(ptr_job);
InternalJob::Pointer sptr_blocker = FindBlockingJob(sptr_job);
if (sptr_blocker == 0)
break;
//queue this job after the job that's blocking it
ChangeState(sptr_job, InternalJob::BLOCKED);
//assert job does not already belong to some other data structure
//Assert.isTrue(job.next() == null);
//Assert.isTrue(job.previous() == null);
sptr_blocker->AddLast(ptr_job);
}
// the job to run must be in the running list before we exit
// the sync block, otherwise two jobs with conflicting rules could start at once
if (ptr_job != 0)
{
InternalJob::Pointer sptr_job(ptr_job);
ChangeState(sptr_job, InternalJob::ABOUT_TO_RUN);
}
return ptr_job.Cast ();
}
}
//TODO Job families
//void
//JobManager
//::Select(List members, Object family, InternalJob firstJob, int stateMask) {
// if (firstJob == null)
// return;
// InternalJob job = firstJob;
// do {
// //note that job state cannot be NONE at this point
// if ((family == null || job.belongsTo(family)) && ((job.getState() & stateMask) != 0))
// members.add(job);
// job = job.previous();
// } while (job != null && job != firstJob);
// }
//List
//JobManager
//::Select(Object family) {
// return select(family, Job.WAITING | Job.SLEEPING | Job.RUNNING);
// }
//List
//JobManager
//::Select(Object family, int stateMask) {
// List members = new ArrayList();
// synchronized (lock) {
// if ((stateMask & Job.RUNNING) != 0) {
// for (Iterator it = running.iterator(); it.hasNext();) {
// select(members, family, (InternalJob) it.next(), stateMask);
// }
// }
// if ((stateMask & Job.WAITING) != 0)
// select(members, family, waiting.peek(), stateMask);
// if ((stateMask & Job.SLEEPING) != 0)
// select(members, family, sleeping.peek(), stateMask);
// }
// return members;
// }
-// dummy validateRule implemenation
+// dummy validateRule implementation
void JobManager::ValidateRule(ISchedulingRule::Pointer sptr_rule)
{
//null rule always valid
if (sptr_rule == 0)
return;
//contains method must be reflexive
poco_assert(sptr_rule->Contains(sptr_rule))
; //contains method must return false when given an unknown rule
poco_assert(!sptr_rule->Contains(sptr_testRule));
//isConflicting method must be reflexive
poco_assert(sptr_rule->IsConflicting(sptr_rule));
//isConflicting method must return false when given an unknown rule
poco_assert(!sptr_rule->IsConflicting(sptr_testRule));
}
bool JobManager::Cancel(InternalJob::Pointer sptr_job)
{
IProgressMonitor::Pointer sptr_progressMonitor(nullptr);
bool runCanceling = false;
{
Poco::ScopedLock mangerMutex (m_mutex);
switch (sptr_job->GetState())
{
case Job::NONE :
return true;
case Job::RUNNING :
//cannot cancel a job that has already started (as opposed to ABOUT_TO_RUN)
if (sptr_job->InternalGetState() == Job::RUNNING)
{
sptr_progressMonitor = sptr_job->GetProgressMonitor();
runCanceling = sptr_job->IsRunCanceled();
if(runCanceling)
sptr_job->SetRunCanceled(true);
break ;
}
//signal that the job should be canceled before it gets a chance to run
sptr_job->SetAboutToRunCanceled(true);
return false;
default :
ChangeState(sptr_job, Job::NONE);
}
}
//call monitor outside sync block
if (sptr_progressMonitor != 0)
{
if(runCanceling)
{
if (!sptr_progressMonitor->IsCanceled())
sptr_progressMonitor->SetCanceled(true);
sptr_job->Canceling();
}
return false;
}
//only notify listeners if the job was waiting or sleeping
m_JobListeners.Done(sptr_job.Cast(), Status::CANCEL_STATUS(BERRY_STATUS_LOC), false);
return true;
}
IProgressMonitor::Pointer JobManager::CreateMonitor(
Job::Pointer sptr_jobToMonitor)
{
IProgressMonitor::Pointer sptr_monitor(nullptr);
if (m_sptr_progressProvider != 0)
sptr_monitor = m_sptr_progressProvider->CreateMonitor(sptr_jobToMonitor);
if (sptr_monitor == 0)
{
NullProgressMonitor::Pointer sptr_defaultMonitor(new NullProgressMonitor());
return sptr_defaultMonitor;
}
return sptr_monitor;
}
IProgressMonitor::Pointer JobManager::CreateMonitor(InternalJob::Pointer sptr_job, IProgressMonitor::Pointer group, int ticks)
{
{
Poco::ScopedLock managerLock(m_mutex);
//group must be set before the job is scheduled
//this includes the ABOUT_TO_SCHEDULE state, during which it is still
//valid to set the progress monitor
if (sptr_job->GetState() != Job::NONE)
{
IProgressMonitor::Pointer dummy(nullptr);
return dummy;
}
IProgressMonitor::Pointer sptr_monitor(nullptr);
if (m_sptr_progressProvider != 0)
sptr_monitor = m_sptr_progressProvider->CreateMonitor(sptr_job.Cast() , group, ticks);
if (sptr_monitor == 0)
{
// return a default NullprogressMonitor
NullProgressMonitor::Pointer sptr_defaultMonitor(new NullProgressMonitor() );
return sptr_defaultMonitor;
}
return sptr_monitor;
}
}
void JobManager::EndJob(InternalJob::Pointer ptr_job, IStatus::Pointer result, bool notify)
{
Poco::Timestamp::TimeDiff rescheduleDelay(InternalJob::T_NONE);
{
Poco::ScopedLock lock ( m_mutex);
// if the job is finishing asynchronously, there is nothing more to do for now
if (result == Job::ASYNC_FINISH)
return;
//if job is not known then it cannot be done
if (ptr_job->GetState() == Job::NONE)
return;
ptr_job->SetResult(result);
ptr_job->SetProgressMonitor(IProgressMonitor::Pointer(nullptr));
ptr_job->SetThread(nullptr);
rescheduleDelay = ptr_job->GetStartTime().epochMicroseconds();
InternalJob::Pointer sptr_job(ptr_job);
ChangeState(sptr_job, Job::NONE);
}
//notify listeners outside sync block
bool reschedule = m_active && rescheduleDelay > InternalJob::T_NONE && ptr_job->ShouldSchedule();
if (notify)
m_JobListeners.Done(ptr_job.Cast(), result, reschedule);
//reschedule the job if requested and we are still active
if (reschedule)
Schedule(ptr_job, rescheduleDelay, reschedule);
}
InternalJob::Pointer JobManager::FindBlockingJob(InternalJob::Pointer waitingJob)
{
if (waitingJob->GetRule() == 0)
return InternalJob::Pointer(nullptr);
{
Poco::ScopedLock managerLock (m_mutex);
if (m_running.empty() )
{
InternalJob::Pointer dummy;
return (dummy);
}
//check the running jobs
bool hasBlockedJobs = false;
QSet::Iterator it;
for ( it = m_running.begin(); it != m_running.end(); it ++ )
{
InternalJob::Pointer sptr_job = *it ++;
if (waitingJob->IsConflicting(sptr_job))
return sptr_job;
if (!hasBlockedJobs)
hasBlockedJobs = sptr_job->Previous() != 0;
}
// there are no blocked jobs, so we are done
if (!hasBlockedJobs)
{
InternalJob::Pointer dummy;
return (dummy);
}
//check all jobs blocked by running jobs
QSet::Iterator it_blocked;
for( it_blocked = m_running.begin(); it_blocked != m_running.end(); it_blocked ++ )
{
InternalJob::Pointer sptr_job = *it_blocked ++;
while (true)
{
sptr_job = sptr_job->Previous();
if (sptr_job == 0)
break;
if (waitingJob->IsConflicting(sptr_job))
return sptr_job;
}
}
}
InternalJob::Pointer sptr_null;
return (sptr_null);
}
bool JobManager::IsActive()
{
return m_active;
}
bool JobManager::IsBlocking(InternalJob::Pointer sptr_runningJob)
{
{
Poco::ScopedLock lockMe (m_mutex);
// if this job isn't running, it can't be blocking anyone
if (sptr_runningJob->GetState() != Job::RUNNING)
return false;
// if any job is queued behind this one, it is blocked by it
InternalJob::Pointer ptr_previous = sptr_runningJob->Previous();
while (ptr_previous != 0)
{
// ignore jobs of lower priority (higher priority value means lower priority)
if (ptr_previous->GetPriority() < sptr_runningJob->GetPriority())
{
if (!ptr_previous->IsSystem())
return true;
// TODO Implicit Jobs
// implicit jobs should interrupt unless they act on behalf of system jobs
// if (previous instanceof ThreadJob && ((ThreadJob) previous).shouldInterrupt())
// return true;
}
ptr_previous = ptr_previous->previous;
}
// none found
return false;
}
}
//void
//JobManager
//::Join(InternalJob job) {
// final IJobChangeListener listener;
// final Semaphore barrier;
// synchronized (lock) {
// int state = job.getState();
// if (state == Job.NONE)
// return;
// //don't join a waiting or sleeping job when suspended (deadlock risk)
// if (suspended && state != Job.RUNNING)
// return;
// //it's an error for a job to join itself
// if (state == Job.RUNNING && job.getThread() == Thread.currentThread())
// throw new IllegalStateException("Job attempted to join itself"); //$NON-NLS-1$
// //the semaphore will be released when the job is done
// barrier = new Semaphore(null);
// listener = new JobChangeAdapter() {
// public void done(IJobChangeEvent event) {
// barrier.release();
// }
// };
// job.addJobChangeListener(listener);
// //compute set of all jobs that must run before this one
// //add a listener that removes jobs from the blocking set when they finish
// }
// //wait until listener notifies this thread.
// try {
// while (true) {
// //notify hook to service pending syncExecs before falling asleep
// lockManager.aboutToWait(job.getThread());
// try {
// if (barrier.acquire(Long.MAX_VALUE))
// break;
// } catch (InterruptedException e) {
// //loop and keep trying
// }
// }
// } finally {
// lockManager.aboutToRelease();
// job.removeJobChangeListener(listener);
// }
// }
bool JobManager::RunNow(InternalJob::Pointer sptr_job)
{
{
Poco::ScopedLock lockMe (m_mutex);
//cannot start if there is a conflicting job
if (FindBlockingJob(sptr_job) != 0)
return false;
ChangeState(sptr_job, Job::RUNNING);
sptr_job->SetProgressMonitor(IProgressMonitor::Pointer(new NullProgressMonitor()));
sptr_job->Run(IProgressMonitor::Pointer(nullptr));
}
return true;
}
void JobManager::Schedule(InternalJob::Pointer job, Poco::Timestamp::TimeDiff delay, bool reschedule)
{
if (!m_active)
throw Poco::IllegalStateException("Job manager has been shut down.");
poco_assert(job); // "Job is null"
poco_assert(delay >= 0); // "Scheduling delay is negative"
{
Poco::ScopedLock managerLock (m_mutex);
//if the job is already running, set it to be rescheduled when done
if (job->GetState() == Job::RUNNING)
{
job->SetStartTime(delay);
return;
}
//can't schedule a job that is waiting or sleeping
if (job->InternalGetState() != Job::NONE)
return;
//remember that we are about to schedule the job
//to prevent multiple schedule attempts from succeeding (bug 68452)
InternalJob::Pointer sptr_job(job);
ChangeState(sptr_job, InternalJob::ABOUT_TO_SCHEDULE);
}
//notify listeners outside sync block
m_JobListeners.Scheduled(job.Cast(), delay, reschedule);
//schedule the job
DoSchedule(job, delay);
//call the pool outside sync block to avoid deadlock
m_Pool->JobQueued();
}
bool JobManager::Sleep(InternalJob::Pointer job)
{
{
Poco::ScopedLock lockMe (m_mutex);
InternalJob::Pointer sptr_job(job);
switch (job->GetState())
{
case Job::RUNNING :
//cannot be paused if it is already running (as opposed to ABOUT_TO_RUN)
if (job->InternalGetState() == Job::RUNNING)
return false;
//job hasn't started running yet (aboutToRun listener)
break;
case Job::SLEEPING :
//update the job wake time
job->SetStartTime(InternalJob::T_INFINITE);
//change state again to re-shuffle the sleep queue
ChangeState(sptr_job, Job::SLEEPING);
return true;
case Job::NONE :
return true;
case Job::WAITING :
//put the job to sleep
break;
}
job->SetStartTime(InternalJob::T_INFINITE);
ChangeState(sptr_job, Job::SLEEPING);
}
m_JobListeners.Sleeping(job.Cast());
return true;
}
void JobManager::SetPriority(InternalJob::Pointer job, int newPriority)
{
{
Poco::ScopedLock lockMe (m_mutex);
InternalJob::Pointer sptr_job(job);
int oldPriority = job->GetPriority();
if (oldPriority == newPriority)
return;
job->InternalSetPriority(newPriority);
//if the job is waiting to run, re-shuffle the queue
if (sptr_job->GetState() == Job::WAITING)
{
Poco::Timestamp oldStart = job->GetStartTime();
job->SetStartTime(oldStart += (DelayFor(newPriority) - DelayFor(oldPriority)));
m_JobQueueWaiting.Resort(job);
}
}
}
Poco::Timespan::TimeDiff JobManager::SleepHint()
{
Poco::ScopedLock managerLock (m_mutex);
// wait forever if job manager is suspended
if (m_suspended)
return InternalJob::T_INFINITE;
if (!m_JobQueueWaiting.IsEmpty())
return 0;
// return the anticipated time that the next sleeping job will wake
InternalJob::Pointer ptr_next(nullptr);
ptr_next = m_JobQueueSleeping.Peek();
if (ptr_next == 0)
return InternalJob::T_INFINITE;
Poco::Timestamp tmp_startTime = ptr_next->GetStartTime();
Poco::Timestamp tmp_currentTime;
Poco::Timestamp::TimeDiff timeToStart = tmp_startTime - tmp_currentTime;
return timeToStart;
}
Job::Pointer JobManager::StartJob()
{
Job::Pointer job(nullptr);
while (true)
{
job = NextJob();
if (!job)
return Job::Pointer(nullptr);
//must perform this outside sync block because it is third party code
bool shouldRun = job->ShouldRun();
//check for listener veto
if (shouldRun)
m_JobListeners.AboutToRun(job);
//listeners may have canceled or put the job to sleep
bool endJob = false;
{
Poco::ScopedLock lock(m_mutex);
InternalJob::Pointer internal = job;
if (internal->InternalGetState() == InternalJob::ABOUT_TO_RUN)
{
if (shouldRun && !internal->IsAboutToRunCanceled())
{
internal->SetProgressMonitor(CreateMonitor(job));
//change from ABOUT_TO_RUN to RUNNING
internal->InternalSetState(Job::RUNNING);
break;
}
internal->SetAboutToRunCanceled(false);
endJob = true;
//fall through and end the job below
}
}
if (endJob)
{
//job has been vetoed or canceled, so mark it as done
EndJob(job,Status::CANCEL_STATUS(BERRY_STATUS_LOC), true);
continue;
}
}
m_JobListeners.Running(job);
return job;
}
void JobManager::WakeUp(InternalJob::Pointer job, Poco::Timestamp::TimeDiff delay)
{
poco_assert(delay >= 0); // "Scheduling delay is negative"
{
Poco::ScopedLock m_managerLock (m_mutex);
//cannot wake up if it is not sleeping
if (job->GetState() != Job::SLEEPING)
return;
DoSchedule(job, delay);
}
//call the pool outside sync block to avoid deadlock
m_Pool->JobQueued();
/// IListenerExtension only notify of wake up if immediate
if (delay == 0)
m_JobListeners.Awake(job.Cast());
}
IProgressMonitor::Pointer JobManager::MonitorFor(IProgressMonitor::Pointer sptr_monitor)
{
if(sptr_monitor == 0 || sptr_monitor.Cast() )
{
if(m_sptr_progressProvider != 0 )
sptr_monitor = m_sptr_progressProvider->GetDefaultMonitor();
}
if(sptr_monitor == 0)
{
IProgressMonitor::Pointer sptr_nullProgressMonitor(new NullProgressMonitor());
return sptr_nullProgressMonitor;
}
return sptr_monitor;
}
}
diff --git a/Plugins/org.blueberry.core.jobs/src/internal/berryJobManager.h b/Plugins/org.blueberry.core.jobs/src/internal/berryJobManager.h
index dfc3597689..49f7e5d91b 100644
--- a/Plugins/org.blueberry.core.jobs/src/internal/berryJobManager.h
+++ b/Plugins/org.blueberry.core.jobs/src/internal/berryJobManager.h
@@ -1,431 +1,431 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
//
//
#ifndef _BERRY_JOBMANAGER_H
#define _BERRY_JOBMANAGER_H
#include "berryInternalJob.h"
#include "berryJobQueue.h"
#include "berryWorkerPool.h"
#include "berryJobListeners.h"
#include "berryJob.h"
#include "berryIProgressMonitorWithBlocking.h"
#include "berryIJobManager.h"
#include "berryISchedulingRule.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace berry
{
/**
* Implementation of API type IJobManager
*
* Implementation note: all the data structures of this class are protected
* by a single lock object held as a private field in this class. The JobManager
* instance itself is not used because this class is publicly reachable, and third
* party clients may try to synchronize on it.
*
* The WorkerPool class uses its own monitor for synchronizing its data
* structures. To avoid deadlock between the two classes, the JobManager
* must NEVER call the worker pool while its own monitor is held.
*/
struct BERRY_JOBS JobManager: public IJobManager
{
public:
friend class WorkerPool;
friend struct InternalJob;
friend struct NullRule;
berryObjectMacro(JobManager);
/**
* The unique identifier constant of this plug-in.
*/
static const QString& PI_JOBS();
static bool DEBUG;
static bool DEBUG_BEGIN_END;
static bool DEBUG_DEADLOCK;
static bool DEBUG_LOCKS;
static bool DEBUG_TIMING;
static bool DEBUG_SHUTDOWN;
/**
* Status code constant indicating an error occurred while running a plug-in.
* For backward compatibility with Platform.PLUGIN_ERROR left at (value = 2).
*/
static const int PLUGIN_ERROR;
/// const ImplicitJobs iImplicitJobs = new ImplicitJobs(this);
/**
* The singleton job manager instance. It must be a singleton because
* all job instances maintain a reference (as an optimization) and have no way
* of updating it.
*/
static JobManager* GetInstance();
/**
* For debugging purposes only
*/
static std::string PrintState(int state);
/**
* Note that although this method is not API, clients have historically used
* it to force jobs shutdown in cases where OSGi shutdown does not occur.
* For this reason, this method should be considered near-API and should not
* be changed if at all possible.
*/
static void Shutdown();
// void Cancel(Object family) ;
IProgressMonitor::Pointer CreateProgressGroup() override;
Job* CurrentJob();
// void EndRule(ISchedulingRule rule) ;
// Job[] Find(Object family) ;
// LockManager GetLockManager() {
// return lockManager;
// }
bool IsIdle() override;
bool IsSuspended() override;
// void Join(final Object family, IProgressMonitor monitor) throws InterruptedException, OperationCanceledException );
// ILock NewLock() ;
/**
* @see IJobManager#RemoveChangeListener(IJobChangeListener*)
*/
void RemoveJobChangeListener(IJobChangeListener* listener) override;
// /**
//* report to the progress monitor that this thread is blocked, supplying
//* an information message, and if possible the job that is causing the blockage.
//* important: an invocation of this method must be followed eventually be
//* an invocation of ReportUnblocked.
//* @param monitor the monitor to report blocking to
//* @param BlockingJob the job that is blocking this thread, or null
//* @see #Reportunblocked
//*/
void ReportBlocked( IProgressMonitor::Pointer monitor, InternalJob::Pointer blockingjob) const ;
/**
* Reports that this thread was blocked, but is no longer blocked and is able
* to proceed.
* @param monitor The monitor to report unblocking to.
* @see #ReportBlocked
*/
void ReportUnblocked(IProgressMonitor::Pointer monitor) const ;
/**
* @have a look at IJobManager Resume
*/
void Resume();
// /**
// * @have a look at IJobManager Resume
// */
// void Resume(ISchedulingRule::Pointer rule)const ;
/**
* @have a look at IJobManager SetProgressProvider
*/
void SetProgressProvider(ProgressProvider::Pointer provider) override;
void SetRule(InternalJob::Pointer job, ISchedulingRule::Pointer rule);
// /*
// * @see IJobManager#sleep(std::string)
// */
// void Sleep(Object family) ;
void Suspend();
/*
* @see schedule(long)
*/
void Schedule(InternalJob::Pointer job, Poco::Timestamp::TimeDiff delay, bool reschedule);
// void Suspend(ISchedulingRule::Pointer rule, IProgressMonitor::Pointer monitor)const ;
// void TransferRule(ISchedulingRule rule, Thread destinationThread) ;
// void SetLockListener(LockListener listener) ;
// /**
// * Puts a job to sleep. Returns true if the job was successfully put to sleep.
// */
// void WakeUp(Object family) ;
void AddJobChangeListener(IJobChangeListener* listener) override;
// void beginRule(ISchedulingRule rule, IProgressMonitor monitor) ;
protected:
/**
* Cancels a job
*/
bool Cancel(InternalJob::Pointer job);
/**
* Returns a new progress monitor for this job, belonging to the given
* progress group. Returns null if it is not a valid time to set the job's group.
*/
IProgressMonitor::Pointer CreateMonitor(InternalJob::Pointer job,
IProgressMonitor::Pointer group, int ticks);
/**
* Indicates that a job was running, and has now finished. Note that this method
* can be called under OutOfMemoryError conditions and thus must be paranoid
* about allocating objects.
*/
/// optional Extension IStatus for implementation help have a look at the Java JobAPI
void EndJob(InternalJob::Pointer job,IStatus::Pointer result, bool notify);
/**
* Returns a running or blocked job whose scheduling rule conflicts with the
* scheduling rule of the given waiting job. Returns null if there are no
* conflicting jobs. A job can only run if there are no running jobs and no blocked
* jobs whose scheduling rule conflicts with its rule.
*/
InternalJob::Pointer FindBlockingJob(InternalJob::Pointer waitingJob);
/**
* Returns whether the job manager is active (has not been shutdown).
*/
bool IsActive();
/**
* Returns true if the given job is blocking the execution of a non-system
* job.
*/
bool IsBlocking(InternalJob::Pointer runningJob);
// void Join(InternalJob job) ;
/**
* Attempts to immediately start a given job. Returns true if the job was
* successfully started, and false if it could not be started immediately
* due to a currently running job with a conflicting rule. Listeners will never
* be notified of jobs that are run in this way.
*/
bool RunNow(InternalJob::Pointer sptr_job);
/**
* Puts a job to sleep. Returns true if the job was successfully put to sleep.
*/
bool Sleep(InternalJob::Pointer job);
/**
* Changes a job priority.
*/
void SetPriority(InternalJob::Pointer job, int newPriority);
/**
* Returns the estimated time in milliseconds before the next job is scheduled
* to wake up. The result may be negative. Returns InternalJob.T_INFINITE if
* there are no sleeping or waiting jobs.
*/
Poco::Timespan::TimeDiff SleepHint();
/**
* Returns the next job to be run, or null if no jobs are waiting to run.
* The worker must call endJob when the job is finished running.
*/
Job::Pointer StartJob();
/*
* @see Job#WakeUp(long)
*/
void WakeUp(InternalJob::Pointer job, Poco::Timestamp::TimeDiff delay);
private:
JobManager();
/* Poco Mutex for synchronizing purposes */
Poco::Mutex m_mutex;
// Dummy Null rule to validate SchedulingRules implemented by clients
SmartPointer sptr_testRule;
// //ToDO static const ISchedulingRule nullRule = new ISchedulingRule() {
// public bool Contains(ISchedulingRule rule) ;
// public boolean IsConflicting(ISchedulingRule rule) ;
/**
* True if this manager is active, and false otherwise. A job manager
* starts out active, and becomes inactive if it has been shutdown
* and not restarted.
*/
volatile bool m_active;
JobListeners m_JobListeners;
//
// /**
// * The lock for synchronizing all activity in the job manager. To avoid deadlock,
// * this lock must never be held for extended periods, and must never be
// * held while third party code is being called.
// */
// // private final Object lock = new Object();
// static const Object lock ;
//
// //private LockManager lockManager = new LockManager();
- // static const LockManger lockManager;
+ // static const LockManager lockManager;
/**
* The pool of worker threads.
*/
WorkerPool::Pointer m_Pool;
ProgressProvider::Pointer m_sptr_progressProvider;
/**
* Jobs that are currently running. Should only be modified from changeState
*/
QSet m_running;
/**
* Jobs that are sleeping. Some sleeping jobs are scheduled to wake
* up at a given start time, while others will sleep indefinitely until woken.
* Should only be modified from changeState
*/
JobQueue m_JobQueueSleeping;
/**
* jobs that are waiting to be run. Should only be modified from changeState
*/
JobQueue m_JobQueueWaiting;
/**
* True if this manager has been suspended, and false otherwise. A job manager
* starts out not suspended, and becomes suspended when suspend
* is invoked. Once suspended, no jobs will start running until resume
* is cancelled.
*/
bool m_suspended;
/**
* Counter to record wait queue insertion order.
*/
long long m_waitQueueCounter;
// /**
// * For debugging purposes only
// */
// const std::string PrintJobName(Job job);
/**
* Atomically updates the state of a job, adding or removing from the
* necessary queues or sets.
*/
void ChangeState(InternalJob::Pointer job, int newState);
/**
* Returns a new progress monitor for this job. Never returns null.
*/
IProgressMonitor::Pointer CreateMonitor(Job::Pointer sptr_jobToMonitor);
/**
* Returns the delay in milliseconds that a job with a given priority can
* tolerate waiting.
*/
Poco::Timestamp::TimeDiff DelayFor(int priority);
/**
* Performs the scheduling of a job. Does not perform any notifications.
*/
void DoSchedule(InternalJob::Pointer job, Poco::Timestamp::TimeDiff delay);
/**
* Shuts down the job manager. Currently running jobs will be told
* to stop, but worker threads may still continue processing.
* (note: This implemented IJobManager.Shutdown which was removed
* due to problems caused by premature shutdown)
*/
void DoShutdown();
// void InitDebugOptions() ;
/**
* Removes and returns the first waiting job in the queue. Returns null if there
* are no items waiting in the queue. If an item is removed from the queue,
* it is moved to the running jobs list.
*/
Job::Pointer NextJob();
/**
* Returns a non-null progress monitor instance. If the monitor is null,
* returns the default monitor supplied by the progress provider, or a
* NullProgressMonitor if no default monitor is available.
*/
IProgressMonitor::Pointer MonitorFor(IProgressMonitor::Pointer monitor);
// /**
// * Adds all family members in the list of jobs to the collection
// */
// void Select(List members, Object family, InternalJob firstJob, int stateMask) ;
//
// /**
// * Returns a list of all jobs known to the job manager that belong to the given family.
// */
// List Select(Object family) ;
//
// /**
// * Returns a list of all jobs known to the job manager that belong to the given
// * family and are in one of the provided states.
// */
// List Select(Object family, int stateMask) ;
/**
* Validates that the given scheduling rule obeys the constraints of
* scheduling rules as described in the ISchedulingRule
*/
void ValidateRule(ISchedulingRule::Pointer rule);
};
}
#endif /* _BERRY_TEMPLATE_H */
diff --git a/Plugins/org.blueberry.core.jobs/src/internal/berryJobQueue.cpp b/Plugins/org.blueberry.core.jobs/src/internal/berryJobQueue.cpp
index 8818936f83..6d2dd57b5c 100644
--- a/Plugins/org.blueberry.core.jobs/src/internal/berryJobQueue.cpp
+++ b/Plugins/org.blueberry.core.jobs/src/internal/berryJobQueue.cpp
@@ -1,142 +1,142 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include "berryJobQueue.h"
// changed Java JobQueue implementation ..
// if only one element is in the queue than InternalJob->next and InternalJob->previous pointer are pointing to 0 and not to the Element itself
// I think its better .. will see
namespace berry
{
class DummyJob: public InternalJob
{
public:
IStatus::Pointer Run(IProgressMonitor::Pointer) override
{
return Status::OK_STATUS(BERRY_STATUS_LOC);
}
DummyJob() :
InternalJob("Queue-Head")
{
}
};
JobQueue::JobQueue(bool allowConflictOvertaking) :
dummy(new DummyJob()), m_allowConflictOvertaking(allowConflictOvertaking)
{
dummy->SetNext(dummy);
dummy->SetPrevious(dummy);
}
-//TODO JobQueue Constructor IStatus Implementierung
+//TODO JobQueue Constructor IStatus Implementation
//TODO Constructor JobQueue IStatus .. implementation
// public JobQueue(boolean allowConflictOvertaking) {
// //compareTo on dummy is never called
// dummy = new InternalJob("Queue-Head") {//$NON-NLS-1$
// public IStatus run(IProgressMonitor m) {
// return Status.OK_STATUS;
// }
// };
// dummy.setNext(dummy);
// dummy.setPrevious(dummy);
// this.allowConflictOvertaking = allowConflictOvertaking;
//}
bool JobQueue::CanOvertake(InternalJob::Pointer newEntry,
InternalJob::Pointer queueEntry)
{
//can never go past the end of the queue
if (queueEntry == dummy.GetPointer())
return false;
//if the new entry was already in the wait queue, ensure it is re-inserted in correct position (bug 211799)
if (newEntry->GetWaitQueueStamp() > 0 && newEntry->GetWaitQueueStamp()
< queueEntry->GetWaitQueueStamp())
return true;
//if the new entry has lower priority, there is no need to overtake the existing entry
if ((queueEntry == newEntry))
return false;
// the new entry has higher priority, but only overtake the existing entry if the queue allows it
InternalJob::Pointer sptr_queueEntry(queueEntry);
return m_allowConflictOvertaking || !newEntry->IsConflicting(sptr_queueEntry);
}
void JobQueue::Clear()
{
dummy->SetNext(dummy);
dummy->SetPrevious(dummy);
}
// notice: important that the first element in the queue is internally set as a dummy element
InternalJob::Pointer JobQueue::Dequeue()
{
InternalJob::Pointer ptr_dummyPrevious = dummy->Previous();
// sets previous pointer to 0 if there is only 1 Element in the queue
if (ptr_dummyPrevious == dummy)
{
dummy->previous = nullptr;
return dummy;
}
return ptr_dummyPrevious->Remove();
}
void JobQueue::Enqueue(InternalJob::Pointer newEntry)
{
InternalJob::Pointer tail = dummy->Next();
//overtake lower priority jobs. Only overtake conflicting jobs if allowed to
while (CanOvertake(newEntry, tail))
tail = tail->Next();
InternalJob::Pointer tailPrevious = tail->Previous();
newEntry->SetNext(tail);
newEntry->SetPrevious(tailPrevious);
tailPrevious->SetNext(newEntry);
tail->SetPrevious(newEntry);
}
void JobQueue::Remove(InternalJob::Pointer jobToRemove)
{
jobToRemove->Remove();
}
void JobQueue::Resort(InternalJob::Pointer entry)
{
this->Remove(entry);
this->Enqueue(entry);
}
bool JobQueue::IsEmpty()
{
return this->dummy->next == dummy;
}
InternalJob::Pointer JobQueue::Peek()
{
return dummy->Previous() == dummy ? InternalJob::Pointer(nullptr)
: dummy->Previous();
}
}
diff --git a/Plugins/org.blueberry.core.jobs/src/internal/berryWorkerPool.cpp b/Plugins/org.blueberry.core.jobs/src/internal/berryWorkerPool.cpp
index 9360e6ea59..41abb8fc98 100644
--- a/Plugins/org.blueberry.core.jobs/src/internal/berryWorkerPool.cpp
+++ b/Plugins/org.blueberry.core.jobs/src/internal/berryWorkerPool.cpp
@@ -1,215 +1,215 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#define NOMINMAX
#include "berryWorkerPool.h"
#include "berryJobManager.h"
#include
#include
#include
namespace berry
{
WorkerPool::WorkerPool(JobManager* myJobManager) :
m_ptrManager(myJobManager), m_numThreads(0), m_sleepingThreads(0), m_threads(
10), m_busyThreads(0)
// m_isDaemon(false),
{
}
const long WorkerPool::BEST_BEFORE = 60000;
const int WorkerPool::MIN_THREADS = 1;
void WorkerPool::Shutdown()
{
Poco::ScopedLock LockMe(m_mutexOne);
for(int i = 0; i<= m_numThreads; i++)
{
notify();
}
}
void WorkerPool::Add(Worker::Pointer worker)
{
Poco::Mutex::ScopedLock lock(m_mutexOne);
m_threads.push_back(worker);
}
void WorkerPool::DecrementBusyThreads()
{
Poco::ScopedLock lockOne(m_mutexOne);
//impossible to have less than zero busy threads
if (--m_busyThreads < 0)
{
//TODO Decrementbusythreads if (jobmanager.debug) assert.istrue(false, integer.tostring(busythreads));
m_busyThreads = 0;
}
}
void WorkerPool::IncrementBusyThreads()
{
Poco::ScopedLock lockOne(m_mutexOne);
if (++m_busyThreads > m_numThreads)
{
m_busyThreads = m_numThreads;
}
}
bool WorkerPool::Remove(Worker::Pointer worker)
{
Poco::ScopedLock lockOne(m_mutexOne);
auto end = std::remove(m_threads.begin(),
m_threads.end(), worker);
bool removed = end != m_threads.end();
m_threads.erase(end);
return removed;
}
void WorkerPool::EndWorker(Worker::Pointer sptr_worker)
{
Poco::ScopedLock lock(m_mutexOne);
Remove(sptr_worker);
}
void WorkerPool::Sleep(long duration)
{
Poco::ScopedLock lock(m_mutexOne);
m_sleepingThreads++;
m_busyThreads--;
try
{
wait(duration);
throw FinallyThrowException();
} catch (FinallyThrowException&)
{
m_sleepingThreads--;
m_busyThreads++;
} catch (...)
{
m_sleepingThreads--;
m_busyThreads++;
}
}
InternalJob::Pointer WorkerPool::StartJob(Worker* worker)
{
// if we're above capacity, kill the thread
{
Poco::Mutex::ScopedLock lockOne(m_mutexOne);
if (!m_ptrManager->IsActive())
{
// must remove the worker immediately to prevent all threads from expiring
Worker::Pointer sptr_worker(worker);
EndWorker(sptr_worker);
return InternalJob::Pointer(nullptr);
}
//set the thread to be busy now in case of reentrant scheduling
IncrementBusyThreads();
}
Job::Pointer ptr_job(nullptr);
try
{
ptr_job = m_ptrManager->StartJob();
//spin until a job is found or until we have been idle for too long
Poco::Timestamp idleStart;
while (m_ptrManager->IsActive() && ptr_job == 0)
{
long tmpSleepTime = long(m_ptrManager->SleepHint());
if (tmpSleepTime > 0)
Sleep(std::min(tmpSleepTime, BEST_BEFORE));
ptr_job = m_ptrManager->StartJob();
//if we were already idle, and there are still no new jobs, then the thread can expire
{
Poco::Mutex::ScopedLock lockOne(m_mutexOne);
Poco::Timestamp tmpCurrentTime;
long long tmpTime = tmpCurrentTime - idleStart;
if (ptr_job == 0 && (tmpTime > BEST_BEFORE) && (m_numThreads
- m_busyThreads) > MIN_THREADS)
{
//must remove the worker immediately to prevent all threads from expiring
Worker::Pointer sptr_worker(worker);
EndWorker(sptr_worker);
return InternalJob::Pointer(nullptr);
}
}
}
if (ptr_job != 0)
{
//if this job has a rule, then we are essentially acquiring a lock
//if ((job.getRule() != 0) && !(job instanceof ThreadJob)) {
- // //don't need to re-aquire locks because it was not recorded in the graph
+ // //don't need to re-acquire locks because it was not recorded in the graph
// //that this thread waited to get this rule
// manager.getLockManager().addLockThread(Thread.currentThread(), job.getRule());
// }
//see if we need to wake another worker
if (m_ptrManager->SleepHint() <= 0)
JobQueued();
}
throw FinallyThrowException();
} catch (FinallyThrowException&)
{
//decrement busy thread count if we're not running a job
if (ptr_job == 0)
DecrementBusyThreads();
} catch (...)
{
DecrementBusyThreads();
}
return ptr_job;
}
void WorkerPool::JobQueued()
{
Poco::ScopedLock lockOne(m_mutexOne);
//if there is a sleeping thread, wake it up
if (m_sleepingThreads > 0)
{
notify();
return;
}
//create a thread if all threads are busy
if (m_busyThreads >= m_numThreads)
{
WorkerPool::WeakPtr wp_WorkerPool(WorkerPool::Pointer(this));
Worker::Pointer sptr_worker(new Worker(wp_WorkerPool));
Add(sptr_worker);
sptr_worker->Start();
return;
}
}
void WorkerPool::EndJob(InternalJob::Pointer job, IStatus::Pointer result) {
DecrementBusyThreads();
//TODO LockManager
// //need to end rule in graph before ending job so that 2 threads
// //do not become the owners of the same rule in the graph
// if ((job.getRule() != null) && !(job instanceof ThreadJob)) {
// //remove any locks this thread may be owning on that rule
// manager.getLockManager().removeLockCompletely(Thread.currentThread(), job.getRule());
// }
m_ptrManager->EndJob(job, result, true);
// //ensure this thread no longer owns any scheduling rules
// manager.implicitJobs.endJob(job);
}
}
diff --git a/Plugins/org.blueberry.core.runtime/src/berryIAdapterManager.h b/Plugins/org.blueberry.core.runtime/src/berryIAdapterManager.h
index 96fa476b20..1c09fe9261 100644
--- a/Plugins/org.blueberry.core.runtime/src/berryIAdapterManager.h
+++ b/Plugins/org.blueberry.core.runtime/src/berryIAdapterManager.h
@@ -1,280 +1,280 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef BERRYIADAPTERMANAGER_H_
#define BERRYIADAPTERMANAGER_H_
#include
#include
#include "berryPlatformObject.h"
#include "berryIAdapterFactory.h"
#include
#include
namespace berry
{
/**
* An adapter manager maintains a registry of adapter factories. Clients
* directly invoke methods on an adapter manager to register and unregister
* adapters. All adaptable objects (that is, objects that implement the IAdaptable
* interface) tunnel IAdaptable.getAdapter
invocations to their
- * adapter manager's IAdapterManger.getAdapter
method. The
+ * adapter manager's IAdapterManager.getAdapter
method. The
* adapter manager then forwards this request unmodified to the IAdapterFactory.getAdapter
* method on one of the registered adapter factories.
*
* Adapter factories can be registered programmatically using the registerAdapters
* method. Alternatively, they can be registered declaratively using the
* org.blueberry.core.runtime.adapters
extension point. Factories registered
* with this extension point will not be able to provide adapters until their
* corresponding plugin has been activated.
*
* The following code snippet shows how one might register an adapter of type
* com.example.acme.Sticky
on resources in the workspace.
*
*
* \code
* IAdapterFactory pr = new IAdapterFactory() {
* public Class[] getAdapterList() {
* return new Class[] { com.example.acme.Sticky.class };
* }
* public Object getAdapter(Object adaptableObject, Class adapterType) {
* IResource res = (IResource) adaptableObject;
* QualifiedName key = new QualifiedName("com.example.acme", "sticky-note");
* try {
* com.example.acme.Sticky v = (com.example.acme.Sticky) res.getSessionProperty(key);
* if (v == null) {
* v = new com.example.acme.Sticky();
* res.setSessionProperty(key, v);
* }
* } catch (CoreException e) {
* // unable to access session property - ignore
* }
* return v;
* }
* }
* Platform.getAdapterManager().registerAdapters(pr, IResource.class);
* \endcode
*
*
* This interface can be used without OSGi running.
*
* This interface is not intended to be implemented by clients.
*
* @see IAdaptable
* @see IAdapterFactory
*/
struct org_blueberry_core_runtime_EXPORT IAdapterManager: public Object
{
berryObjectMacro(berry::IAdapterManager);
/**
* This value can be returned to indicate that no applicable adapter factory
* was found.
* @since org.blueberry.equinox.common 3.3
*/
static const int NONE;
/**
* This value can be returned to indicate that an adapter factory was found,
* but has not been loaded.
* @since org.blueberry.equinox.common 3.3
*/
static const int NOT_LOADED;
/**
* This value can be returned to indicate that an adapter factory is loaded.
* @since org.blueberry.equinox.common 3.3
*/
static const int LOADED;
/**
* Returns a Poco::Any object which contains an instance of the given name associated
* with the given adaptable. Returns an empty Poco::Any if no such object can
* be found.
*
* Note that this method will never cause plug-ins to be loaded. If the
* only suitable factory is not yet loaded, this method will return an empty Poco::Any.
* If activation of the plug-in providing the factory is required, use the
* LoadAdapter
method instead.
*
* @param adaptable the adaptable object being queried (usually an instance
* of IAdaptable
)
* @return a Poco::Any castable to the given adapter type, or empty
* if the given adaptable object does not have an available adapter of the
* given type
*/
template
A* GetAdapter(const Object* adaptable)
{
const char* typeName = qobject_interface_iid();
if (typeName == nullptr)
{
BERRY_WARN << "Error getting adapter for '" << Reflection::GetClassName(adaptable) << "': "
<< "Cannot get the interface id for type '" << Reflection::GetClassName()
<< "'. It is probably missing a Q_DECLARE_INTERFACE macro in its header.";
return nullptr;
}
return dynamic_cast(this->GetAdapter(adaptable, typeName, false));
}
/**
* Returns an object which is an instance of the given class name associated
* with the given object. Returns null
if no such object can
* be found.
*
* Note that this method will never cause plug-ins to be loaded. If the
* only suitable factory is not yet loaded, this method will return null
.
* If activation of the plug-in providing the factory is required, use the
* loadAdapter
method instead.
*
* @param adaptable the adaptable object being queried (usually an instance
* of IAdaptable
)
* @param adapterTypeName the fully qualified name of the type of adapter to look up
* @return an object castable to the given adapter type, or null
* if the given adaptable object does not have an available adapter of the
* given type
*/
virtual Object* GetAdapter(const Object* adaptable, const QString& adapterTypeName) = 0;
/**
* Returns whether there is an adapter factory registered that may be able
* to convert adaptable
to an object of type adapterTypeName
.
*
* Note that a return value of true
does not guarantee that
* a subsequent call to GetAdapter
with the same arguments
* will return a non-empty result. If the factory's plug-in has not yet been
* loaded, or if the factory itself returns nothing, then
* GetAdapter
will still return an empty Poco::Any.
*
* @param adaptableType the adaptable object being queried (usually an instance
* of IAdaptable
)
* @param adapterType the fully qualified class name of an adapter to
* look up
* @return true
if there is an adapter factory that claims
* it can convert adaptable
to an object of type adapterType
,
* and false
otherwise.
*/
virtual bool HasAdapter(const Object* adaptableType, const QString& adapterType) = 0;
template
int QueryAdapter(const Object* adaptable)
{
const char* typeName = qobject_interface_iid();
if (typeName == nullptr)
{
BERRY_WARN << "Error querying adapter manager for '" << Reflection::GetClassName(adaptable) << "': "
<< "Cannot get the interface id for type '" << Reflection::GetClassName()
<< "'. It is probably missing a Q_DECLARE_INTERFACE macro in its header.";
return NONE;
}
return this->QueryAdapter(adaptable, typeName);
}
/**
* Returns a status of an adapter factory registered that may be able
* to convert adaptable
to an object of type adapterTypeName
.
*
* One of the following values can be returned:
* - {@link berry::IAdapterManager::NONE} if no applicable adapter factory was found;
* - {@link berry::IAdapterManager::NOT_LOADED} if an adapter factory was found, but has not been loaded;
* - {@link berry::IAdapterManager::LOADED} if an adapter factory was found, and it is loaded.
*
* @param adaptableType the adaptable object being queried (usually an instance
* of IAdaptable
)
* @param adapterType the fully qualified class name of an adapter to
* look up
* @return a status of the adapter
*/
virtual int QueryAdapter(const Object* adaptableType, const QString& adapterType) = 0;
/**
* Returns an object that is an instance of the given class name associated
* with the given object. Returns an empty Poco::Any if no such object can
* be found.
*
* Note that unlike the GetAdapter
methods, this method
* will cause the plug-in that contributes the adapter factory to be loaded
* if necessary. As such, this method should be used judiciously, in order
* to avoid unnecessary plug-in activations. Most clients should avoid
* activation by using GetAdapter
instead.
*
* @param adaptable the adaptable object being queried (usually an instance
* of IAdaptable
)
* @return a Poco::Any castable to the given adapter type, or empty
* if the given adaptable object does not have an available adapter of the
* given type
*/
template
A* LoadAdapter(const Object* adaptable)
{
const char* typeName = qobject_interface_iid();
if (typeName == nullptr)
{
BERRY_WARN << "Error getting adapter for '" << Reflection::GetClassName(adaptable) << "': "
<< "Cannot get the interface id for type '" << Reflection::GetClassName()
<< "'. It is probably missing a Q_DECLARE_INTERFACE macro in its header.";
return nullptr;
}
return dynamic_cast(this->GetAdapter(adaptable, typeName, true));
}
/**
* Registers the given adapter factory as extending objects of the given
* type.
*
* @param factory the adapter factory
* @param adaptableTypeName the fully qualified typename being extended
* @see #UnregisterAdapters
*/
virtual void RegisterAdapters(IAdapterFactory* factory,
const QString& adaptableTypeName) = 0;
/**
* Removes the given adapter factory completely from the list of registered
* factories. Equivalent to calling UnregisterAdapters(IAdapterFactory*, const std::string&)
* on all classes against which it had been explicitly registered. Does
* nothing if the given factory is not currently registered.
*
* @param factory the adapter factory to remove
* @see #RegisterAdapters
*/
virtual void UnregisterAdapters(IAdapterFactory* factory) = 0;
/**
* Removes the given adapter factory from the list of factories registered
* as extending the given class. Does nothing if the given factory and type
* combination is not registered.
*
* @param factory the adapter factory to remove
* @param adaptableTypeName one of the type names against which the given factory is
* registered
* @see #RegisterAdapters
*/
virtual void UnregisterAdapters(IAdapterFactory* factory,
const QString& adaptableTypeName) = 0;
private:
virtual Object* GetAdapter(const Object* adaptable, const QString& adapterType, bool force) = 0;
};
} // namespace berry
Q_DECLARE_INTERFACE(berry::IAdapterManager, "org.blueberry.service.IAdapterManager")
#endif /*BERRYIADAPTERMANAGER_H_*/
diff --git a/Plugins/org.blueberry.core.runtime/src/berryIStatus.h b/Plugins/org.blueberry.core.runtime/src/berryIStatus.h
index cad224941c..c5fa114bf4 100644
--- a/Plugins/org.blueberry.core.runtime/src/berryIStatus.h
+++ b/Plugins/org.blueberry.core.runtime/src/berryIStatus.h
@@ -1,199 +1,199 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef BERRYISTATUS_H_
#define BERRYISTATUS_H_
#include
#include
#include
namespace berry
{
/**
* A status object represents the outcome of an operation.
* All CoreException
s carry a status object to indicate
* what went wrong. Status objects are also returned by methods needing
* to provide details of failures (e.g., validation methods).
*
* A status carries the following information:
*
* - plug-in identifier (required)
* - severity (required)
* - status code (required)
* - message (required) - localized to current locale
* - exception (optional) - for problems stemming from a failure at
* a lower level
*
* Some status objects, known as multi-statuses, have other status objects
* as children.
*
*
* The class Status
is the standard public implementation
* of status objects; the subclass MultiStatus
is the
* implements multi-status objects.
*
* This interface can be used without OSGi running.
*
* @see MultiStatus
* @see Status
*/
struct org_blueberry_core_runtime_EXPORT IStatus: public Object
{
berryObjectMacro(berry::IStatus);
enum Severity
{
/** Status severity constant (value 0) indicating this status represents the nominal case.
* This constant is also used as the status code representing the nominal case.
*/
OK_TYPE = 0x00,
/** Status type severity (bit mask, value 1) indicating this status is informational only. */
INFO_TYPE = 0x01,
/** Status type severity (bit mask, value 2) indicating this status represents a warning. */
WARNING_TYPE = 0x02,
/** Status type severity (bit mask, value 4) indicating this status represents an error. */
ERROR_TYPE = 0x04,
- /** Status type severity (bit mask, value 8) indicating this status represents a cancelation. */
+ /** Status type severity (bit mask, value 8) indicating this status represents a cancellation. */
CANCEL_TYPE = 0x08
};
Q_DECLARE_FLAGS(Severities, Severity)
/**
* Returns a list of status object immediately contained in this
* multi-status, or an empty list if this is not a multi-status.
*
* @return an array of status objects
* @see #IsMultiStatus()
*/
virtual QList GetChildren() const = 0;
/**
* Returns the plug-in-specific status code describing the outcome.
*
* @return plug-in-specific status code
*/
virtual int GetCode() const = 0;
/**
* Returns the relevant low-level exception, or null
if none.
* For example, when an operation fails because of a network communications
* failure, this might return the java.io.IOException
* describing the exact nature of that failure.
*
* @return the relevant low-level exception, or null
if none
*/
virtual const ctkException* GetException() const = 0;
/**
* Returns the message describing the outcome.
* The message is localized to the current locale.
*
* @return a localized message
*/
virtual QString GetMessage() const = 0;
/**
* Returns the unique identifier of the plug-in associated with this status
* (this is the plug-in that defines the meaning of the status code).
*
* @return the unique identifier of the relevant plug-in
*/
virtual QString GetPlugin() const = 0;
/**
* Returns the severity. The severities are as follows (in
* descending order):
*
- * CANCEL_TYPE
- cancelation occurred
+ * CANCEL_TYPE
- cancellation occurred
* ERROR_TYPE
- a serious error (most severe)
* WARNING_TYPE
- a warning (less severe)
* INFO_TYPE
- an informational ("fyi") message (least severe)
* OK_TYPE
- everything is just fine
*
*
* The severity of a multi-status is defined to be the maximum
* severity of any of its children, or OK
if it has
* no children.
*
*
* @return the severity: one of OK_TYPE
, ERROR_TYPE
,
* INFO_TYPE
, WARNING_TYPE
, or CANCEL_TYPE
*/
virtual Severity GetSeverity() const = 0;
/**
* Returns whether this status is a multi-status.
* A multi-status describes the outcome of an operation
* involving multiple operands.
*
* The severity of a multi-status is derived from the severities
* of its children; a multi-status with no children is
* OK_TYPE
by definition.
* A multi-status carries a plug-in identifier, a status code,
* a message, and an optional exception. Clients may treat
* multi-status objects in a multi-status unaware way.
*
*
* @return true
for a multi-status,
* false
otherwise
* @see #GetChildren()
*/
virtual bool IsMultiStatus() const = 0;
/**
* Returns whether this status indicates everything is okay
* (neither info, warning, nor error).
*
* @return true
if this status has severity
* OK
, and false
otherwise
*/
virtual bool IsOK() const = 0;
/**
* Returns whether the severity of this status matches the given
* severity mask. Note that a status with severity OK_TYPE
* will never match; use isOK
instead to detect
* a status with a severity of OK
.
*
* @param severityMask a mask formed by bitwise or'ing severity mask
* constants (ERROR_TYPE
, WARNING_TYPE
,
* INFO_TYPE
, CANCEL_TYPE
)
* @return true
if there is at least one match,
* false
if there are no matches
* @see #GetSeverity()
* @see #CANCEL_TYPE
* @see #ERROR_TYPE
* @see #WARNING_TYPE
* @see #INFO_TYPE
*/
virtual bool Matches(const Severities& severityMask) const = 0;
virtual QString GetFileName() const = 0;
virtual QString GetMethodName() const = 0;
virtual int GetLineNumber() const = 0;
};
}
Q_DECLARE_OPERATORS_FOR_FLAGS(berry::IStatus::Severities)
#endif /* BERRYISTATUS_H_ */
diff --git a/Plugins/org.blueberry.core.runtime/src/berryObject.h b/Plugins/org.blueberry.core.runtime/src/berryObject.h
index 325abc974d..513786dcd5 100644
--- a/Plugins/org.blueberry.core.runtime/src/berryObject.h
+++ b/Plugins/org.blueberry.core.runtime/src/berryObject.h
@@ -1,241 +1,241 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef BERRYOBJECT_H_
#define BERRYOBJECT_H_
#include
#include "berryMacros.h"
#include "berryMessage.h"
#include
#include
#include
#include
#include
#ifdef _MSC_VER
// disable inheritance by dominance warnings
#pragma warning( disable : 4250 4275 )
#endif
class QDebug;
class QTextStream;
namespace berry {
class org_blueberry_core_runtime_EXPORT Indent
{
public:
/** Standard class typedefs. */
typedef Indent Self;
/** Construct the object with an initial Indentation level. */
Indent(int ind = 0) { m_Indent=ind; }
/**
* Determine the next Indentation level. Keep Indenting by two until the
* a maximum of forty spaces is reached.
*/
Indent GetNextIndent();
/** Print out the Indentation. Basically output a bunch of spaces. */
friend org_blueberry_core_runtime_EXPORT QDebug operator<<(QDebug os, const Indent& o);
private:
int m_Indent;
};
/** \class Object
* \brief Light weight base class for most BlueBerry classes.
*
* Object is copied from itk::LightObject and is the highest
* level base class for most BlueBerry objects. It
* implements reference counting and the API for object printing.
*
*/
class org_blueberry_core_runtime_EXPORT Object
{
private:
mutable Message<> m_DestroyMessage;
public:
typedef Object Self;
typedef berry::SmartPointer Pointer;
typedef berry::SmartPointer ConstPointer;
typedef berry::WeakPointer WeakPtr;
typedef berry::WeakPointer ConstWeakPtr;
static const char* GetStaticClassName();
virtual QString GetClassName() const;
static Reflection::TypeInfo GetStaticTypeInfo();
virtual Reflection::TypeInfo GetTypeInfo() const;
static QList GetStaticSuperclasses();
virtual QList GetSuperclasses() const;
/** Delete an BlueBerry object. This method should always be used to delete an
* object when the new operator was used to create it. Using the C
* delete method will not work with reference counting. */
virtual void Delete();
#ifdef _WIN32
/** Used to avoid dll boundary problems. */
void* operator new(size_t);
void* operator new[](size_t);
void operator delete(void*);
void operator delete[](void*, size_t);
#endif
/**
* Cause the object to print itself out. This is usually used to provide
* detailed information about the object's state. It just calls the
- * header/self/trailer virtual print methods, which can be overriden by
+ * header/self/trailer virtual print methods, which can be overridden by
* subclasses.
*/
QDebug Print(QDebug os, Indent Indent=0) const;
/**
* Returns a string representation of this object. The default
* implementation returns an empty string.
*/
virtual QString ToString() const;
/**
* Returns a hash code value for the object.
*/
virtual uint HashCode() const;
/**
* Override this method to implement a specific "less than" operator
* for associative STL containers.
*/
virtual bool operator<(const Object*) const;
/** Increase the reference count (mark as used by another object). */
void Register() const;
/** Decrease the reference count (release by another object).
* Set del to false if you do not want the object to be deleted if
* the reference count is zero (use with care!) */
void UnRegister(bool del = true) const;
/** Gets the reference count on this object. */
int GetReferenceCount() const
{
return m_ReferenceCount.load();
}
/** Sets the reference count on this object. This is a dangerous
* method, use it with care. */
void SetReferenceCount(int);
inline void AddDestroyListener(const MessageAbstractDelegate<>& delegate) const
{ m_DestroyMessage += delegate; }
inline void RemoveDestroyListener(const MessageAbstractDelegate<>& delegate) const
{ m_DestroyMessage -= delegate; }
/**
* A generic comparison method. Override this method in subclasses and
* cast to your derived class to provide a more detailed comparison.
*/
virtual bool operator==(const Object*) const;
#ifdef BLUEBERRY_DEBUG_SMARTPOINTER
unsigned int GetTraceId() const;
private:
unsigned int m_TraceId;
unsigned int& GetTraceIdCounter() const;
public:
#endif
protected:
friend struct QScopedPointerObjectDeleter;
Object();
virtual ~Object();
/**
* Methods invoked by Print() to print information about the object
* including superclasses. Typically not called by the user (use Print()
* instead) but used in the hierarchical print process to combine the
* output of several classes.
*/
virtual QDebug PrintSelf(QDebug os, Indent indent) const;
virtual QDebug PrintHeader(QDebug os, Indent indent) const;
virtual QDebug PrintTrailer(QDebug os, Indent indent) const;
/** Number of uses of this object by other objects. */
mutable QAtomicInt m_ReferenceCount;
/** Mutex lock to protect modification to the reference count */
mutable QMutex m_ReferenceCountLock;
private:
Object(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
};
// A custom deleter for QScopedPointer
// berry::Object instances in a QScopedPointer should have reference count one,
// such that they are not accidentally deleted when a temporary smart pointer
// pointing to it goes out of scope. This deleter fixes the reference count and
// always deletes the instance. Use a berry::SmartPointer if the lifetime should
// exceed the one of the pointer.
struct QScopedPointerObjectDeleter
{
static inline void cleanup(Object* obj)
{
if (obj == nullptr) return;
obj->UnRegister(false);
delete obj;
}
};
org_blueberry_core_runtime_EXPORT QDebug operator<<(QDebug os, const berry::Indent& o);
}
/**
* This operator allows all subclasses of Object to be printed via QDebug <<.
* It in turn invokes the Print method, which in turn will invoke the
* PrintSelf method that all objects should define, if they have anything
* interesting to print out.
*/
org_blueberry_core_runtime_EXPORT QDebug operator<<(QDebug os, const berry::Object& o);
org_blueberry_core_runtime_EXPORT QDebug operator<<(QDebug os, const berry::SmartPointer& o);
org_blueberry_core_runtime_EXPORT QDebug operator<<(QDebug os, const berry::SmartPointer& o);
org_blueberry_core_runtime_EXPORT QTextStream& operator<<(QTextStream& os, const berry::Object& o);
org_blueberry_core_runtime_EXPORT QTextStream& operator<<(QTextStream& os, const berry::SmartPointer& o);
//org_blueberry_core_runtime_EXPORT QTextStream& operator<<(QTextStream& os, const berry::SmartPointer& o);
Q_DECLARE_METATYPE(berry::Object::Pointer)
org_blueberry_core_runtime_EXPORT uint qHash(const berry::Object& o);
#endif /*BERRYOBJECT_H_*/
diff --git a/Plugins/org.blueberry.core.runtime/src/berryPlatformObject.h b/Plugins/org.blueberry.core.runtime/src/berryPlatformObject.h
index c36c7381eb..e89a1ace00 100755
--- a/Plugins/org.blueberry.core.runtime/src/berryPlatformObject.h
+++ b/Plugins/org.blueberry.core.runtime/src/berryPlatformObject.h
@@ -1,81 +1,81 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef BERRYPLATFORMOBJECT_H_
#define BERRYPLATFORMOBJECT_H_
#include
#include
#include "berryIAdaptable.h"
namespace berry {
/**
* An abstract superclass implementing the IAdaptable
* interface. getAdapter
invocations are directed
* to the platform's adapter manager.
*
* Note: In situations where it would be awkward to subclass this
* class, the same affect can be achieved simply by implementing
* the IAdaptable
interface and explicitly forwarding
* the getAdapter
request to the platform's
- * adapater manager. The method would look like:
+ * adapter manager. The method would look like:
*
* public Object getAdapter(Class adapter) {
* return Platform.getAdapterManager().getAdapter(this, adapter);
* }
*
*
*
* Clients may subclass.
*
*
* @see Platform#getAdapterManager
*/
class org_blueberry_core_runtime_EXPORT PlatformObject : public virtual Object, public virtual IAdaptable
{
public:
berryObjectMacro(berry::PlatformObject);
/**
* Constructs a new platform object.
*/
PlatformObject();
/**
* Returns an object which is an instance of the given class
* associated with this object. Returns null
if
* no such object can be found.
*
* This implementation of the method declared by IAdaptable
* passes the request along to the platform's adapter manager; roughly
* Platform.getAdapterManager().getAdapter(this, adapter)
.
* Subclasses may override this method (however, if they do so, they
* should invoke the method on their superclass to ensure that the
* Platform's adapter manager is consulted).
*
*
* @see IAdaptable#getAdapter
* @see Platform#getAdapterManager
*/
Object* GetAdapter(const QString& adapter) const override;
};
}
#endif /* BERRYPLATFORMOBJECT_H_ */
diff --git a/Plugins/org.blueberry.core.runtime/src/internal/berryApplicationContainer.h b/Plugins/org.blueberry.core.runtime/src/internal/berryApplicationContainer.h
index 45c092537d..778bce9295 100644
--- a/Plugins/org.blueberry.core.runtime/src/internal/berryApplicationContainer.h
+++ b/Plugins/org.blueberry.core.runtime/src/internal/berryApplicationContainer.h
@@ -1,180 +1,180 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef BERRYAPPLICATIONCONTAINER_H
#define BERRYAPPLICATIONCONTAINER_H
#include
#include
#include
#include
#include
struct ctkApplicationLauncher;
struct ctkApplicationRunnable;
namespace berry {
struct IBranding;
struct IExtensionRegistry;
class ApplicationDescriptor;
class ApplicationHandle;
class MainApplicationLauncher;
/*
* This container will discover installed BlueBerry applications and register the
* appropriate ctkApplicationDescriptor service with the service registry.
*/
class ApplicationContainer : public QObject, public QMutex, private IRegistryEventListener,
private ctkServiceTrackerCustomizer
{
Q_OBJECT
private:
static const QString PI_RUNTIME; // = "org.blueberry.core.runtime";
static const QString PT_APPLICATIONS; // = "applications";
static const QString PT_APP_VISIBLE; // = "visible";
static const QString PT_APP_THREAD; // = "thread";
static const QString PT_APP_THREAD_ANY; // = "any";
static const QString PT_APP_CARDINALITY; // = "cardinality";
static const QString PT_APP_CARDINALITY_SINGLETON_GLOBAL; // = "singleton-global";
static const QString PT_APP_CARDINALITY_SINGLETON_SCOPED; // = "singleton-scoped";
static const QString PT_APP_CARDINALITY_UNLIMITED; // = "*";
static const QString PT_APP_ICON; // = "icon";
static const QString PT_PRODUCTS; // = "products";
static const QString EXT_ERROR_APP; // = "org.blueberry.core.runtime.app.error";
static const QString PROP_PRODUCT; // = "blueberry.product";
static const QString PROP_BLUEBERRY_APPLICATION; // = "blueberry.application";
static const QString PROP_BLUEBERRY_APPLICATION_LAUNCH_DEFAULT; // = "blueberry.application.launchDefault";
static const int NOT_LOCKED; // = 0;
static const int LOCKED_SINGLETON_GLOBAL_RUNNING; // = 1;
static const int LOCKED_SINGLETON_GLOBAL_APPS_RUNNING; // = 2;
static const int LOCKED_SINGLETON_SCOPED_RUNNING; // = 3;
static const int LOCKED_SINGLETON_LIMITED_RUNNING; // = 4;
static const int LOCKED_MAIN_THREAD_RUNNING; // = 5;
ctkPluginContext* context;
QMutex lock;
// A map of ApplicationDescriptors keyed by application ID
/* @GuardedBy(lock) */
QHash apps;
IExtensionRegistry* extensionRegistry;
QScopedPointer> launcherTracker;
mutable QScopedPointer branding;
mutable bool missingProductReported;
/* @GuardedBy(lock) */
QList activeHandles; // the currently active application handles
/* @GuardedBy(lock) */
ApplicationHandle* activeMain; // the handle currently running on the main thread
/* @GuardedBy(lock) */
ApplicationHandle* activeGlobalSingleton; // the current global singleton handle
/* @GuardedBy(lock) */
ApplicationHandle* activeScopedSingleton; // the current scoped singleton handle
/* @GuardedBy(lock) */
QHash > activeLimited; // Map of handles that have cardinality limits
mutable QString defaultAppId;
//DefaultApplicationListener defaultAppListener;
ctkApplicationRunnable* defaultMainThreadAppHandle; // holds the default app handle to be run on the main thread
volatile bool missingApp;
QScopedPointer missingAppLauncher;
public:
ApplicationContainer(ctkPluginContext* context, IExtensionRegistry* extensionRegistry);
~ApplicationContainer() override;
void Start();
void Stop();
IBranding* GetBranding() const;
ctkPluginContext* GetContext() const;
void Launch(ApplicationHandle* appHandle);
void Lock(ApplicationHandle* appHandle);
void Unlock(ApplicationHandle* appHandle);
int IsLocked(const ApplicationDescriptor* eclipseApp) const;
void StartDefaultApp(bool delayError);
private:
Q_DISABLE_COPY(ApplicationContainer)
friend class ApplicationHandle;
/*
* Only used to find the default application
*/
ApplicationDescriptor* GetAppDescriptor(const QString& applicationId);
ApplicationDescriptor* CreateAppDescriptor(const SmartPointer& appExtension);
ApplicationDescriptor* RemoveAppDescriptor(const QString& applicationId);
/*
* Registers an ApplicationDescriptor service for each eclipse application
* available in the extension registry.
*/
void RegisterAppDescriptors();
void RegisterAppDescriptor(const QString& applicationId);
/*
* Returns a list of all the available application IDs which are available
* in the extension registry.
*/
QList > GetAvailableAppExtensions() const;
QString GetAvailableAppsMsg() const;
/*
- * Returns the application extension for the specified applicaiton ID.
+ * Returns the application extension for the specified application ID.
* A RuntimeException is thrown if the extension does not exist for the
* given application ID.
*/
SmartPointer GetAppExtension(const QString& applicationId) const;
Q_SLOT void PluginChanged(const ctkPluginEvent& event);
void StopAllApps();
QString GetDefaultAppId() const;
ctkApplicationLauncher* addingService(const ctkServiceReference& reference) override;
void modifiedService(const ctkServiceReference& reference, ctkApplicationLauncher* service) override;
void removedService(const ctkServiceReference& reference, ctkApplicationLauncher* service) override;
void Added(const QList >& extensions) override;
void Added(const QList >& extensionPoints) override;
void Removed(const QList >& extensions) override;
void Removed(const QList >& extensionPoints) override;
void RefreshAppDescriptors();
};
}
#endif // BERRYAPPLICATIONCONTAINER_H
diff --git a/Plugins/org.blueberry.core.runtime/src/internal/berryExtensionRegistry.cpp b/Plugins/org.blueberry.core.runtime/src/internal/berryExtensionRegistry.cpp
index d83da9b8cc..bd600d2bcc 100644
--- a/Plugins/org.blueberry.core.runtime/src/internal/berryExtensionRegistry.cpp
+++ b/Plugins/org.blueberry.core.runtime/src/internal/berryExtensionRegistry.cpp
@@ -1,1340 +1,1340 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include "berryExtensionRegistry.h"
#include "berryCombinedEventDelta.h"
#include "berryConfigurationElement.h"
#include "berryConfigurationElementAttribute.h"
#include "berryConfigurationElementDescription.h"
#include "berryExtension.h"
#include "berryExtensionHandle.h"
#include "berryExtensionPoint.h"
#include "berryExtensionPointHandle.h"
#include "berryExtensionsParser.h"
#include "berryIConfigurationElement.h"
#include "berryIExtension.h"
#include "berryIExtensionPoint.h"
#include "berrySimpleExtensionPointFilter.h"
#include "berryMultiStatus.h"
#include "berryRegistryConstants.h"
#include "berryRegistryContribution.h"
#include "berryRegistryContributor.h"
#include "berryRegistryMessages.h"
#include "berryRegistryObjectFactory.h"
#include "berryRegistryObjectManager.h"
#include "berryRegistryProperties.h"
#include "berryRegistryStrategy.h"
#include "berryStatus.h"
#include
#include
namespace berry {
struct ExtensionRegistry::ListenerInfo {
IExtensionPointFilter filter;
IRegistryEventListener* listener;
ListenerInfo(IRegistryEventListener* listener, const IExtensionPointFilter& filter)
: filter(filter), listener(listener)
{
}
/**
* Used by ListenerList to ensure uniqueness.
*/
bool operator==(const ListenerInfo& another) const
{
return another.listener == this->listener;
}
};
void ExtensionRegistry::Add(const SmartPointer &element)
{
QWriteLocker l(&access);
eventDelta = CombinedEventDelta::RecordAddition();
BasicAdd(element, true);
FireRegistryChangeEvent();
eventDelta.Reset();
}
QString ExtensionRegistry::AddExtension(int extension)
{
Extension::Pointer addedExtension = registryObjects->GetObject(extension, RegistryObjectManager::EXTENSION).Cast();
QString extensionPointToAddTo = addedExtension->GetExtensionPointIdentifier();
ExtensionPoint::Pointer extPoint = registryObjects->GetExtensionPointObject(extensionPointToAddTo);
//orphan extension
if (extPoint.IsNull())
{
registryObjects->AddOrphan(extensionPointToAddTo, extension);
return QString();
}
// otherwise, link them
QList newExtensions = extPoint->GetRawChildren();
newExtensions.push_back(extension);
Link(extPoint, newExtensions);
if (!eventDelta.IsNull())
eventDelta.RememberExtension(extPoint, extension);
return extPoint->GetNamespace();
//return RecordChange(extPoint, extension, ExtensionDelta::ADDED);
}
QString ExtensionRegistry::AddExtensionPoint(int extPoint)
{
ExtensionPoint::Pointer extensionPoint = registryObjects->GetObject(extPoint, RegistryObjectManager::EXTENSION_POINT).Cast();
if (!eventDelta.IsNull())
eventDelta.RememberExtensionPoint(extensionPoint);
QList orphans = registryObjects->RemoveOrphans(extensionPoint->GetUniqueIdentifier());
if (orphans.empty())
return QString();
Link(extensionPoint, orphans);
if (!eventDelta.IsNull())
eventDelta.RememberExtensions(extensionPoint, orphans);
return extensionPoint->GetNamespace();
//return RecordChange(extensionPoint, orphans, ExtensionDelta::ADDED);
}
QSet ExtensionRegistry::AddExtensionsAndExtensionPoints(const SmartPointer& element)
{
// now add and resolve extensions and extension points
QSet affectedNamespaces;
QList extPoints = element->GetExtensionPoints();
for (int i = 0; i < extPoints.size(); i++)
{
QString namespaze = this->AddExtensionPoint(extPoints[i]);
if (!namespaze.isEmpty())
affectedNamespaces.insert(namespaze);
}
QList extensions = element->GetExtensions();
for (int i = 0; i < extensions.size(); i++)
{
QString namespaze = this->AddExtension(extensions[i]);
if (!namespaze.isEmpty())
affectedNamespaces.insert(namespaze);
}
return affectedNamespaces;
}
void ExtensionRegistry::AddListenerInternal(IRegistryEventListener* listener, const IExtensionPointFilter& filter)
{
listeners.Add(ListenerInfo(listener, filter));
}
void ExtensionRegistry::BasicAdd(const SmartPointer& element, bool link)
{
registryObjects->AddContribution(element);
if (!link)
return;
AddExtensionsAndExtensionPoints(element);
SetObjectManagers(registryObjects->CreateDelegatingObjectManager(
registryObjects->GetAssociatedObjects(element->GetContributorId())));
}
void ExtensionRegistry::SetObjectManagers(const SmartPointer& manager)
{
if (!eventDelta.IsNull())
eventDelta.SetObjectManager(manager);
}
void ExtensionRegistry::BasicRemove(const QString& contributorId)
{
// ignore anonymous namespaces
RemoveExtensionsAndExtensionPoints(contributorId);
QHash associatedObjects = registryObjects->GetAssociatedObjects(contributorId);
registryObjects->RemoveObjects(associatedObjects);
registryObjects->AddNavigableObjects(associatedObjects); // put the complete set of navigable objects
SetObjectManagers(registryObjects->CreateDelegatingObjectManager(associatedObjects));
registryObjects->RemoveContribution(contributorId);
registryObjects->RemoveContributor(contributorId);
}
void ExtensionRegistry::FireRegistryChangeEvent()
{
// if there is nothing to say, just bail out
if (listeners.IsEmpty())
{
return;
}
// for thread safety, create tmp collections
QList tmpListeners = listeners.GetListeners();
// do the notification asynchronously
//strategy->ScheduleChangeEvent(tmpListeners, tmpDeltas, this);
this->ScheduleChangeEvent(tmpListeners, eventDelta);
}
//RegistryDelta ExtensionRegistry::GetDelta(const QString& namespaze) const
//{
// // is there a delta for the plug-in?
// RegistryDelta existingDelta = deltas.value(namespaze);
// if (existingDelta != null)
// return existingDelta;
// //if not, create one
// RegistryDelta delta = new RegistryDelta();
// deltas.put(namespace, delta);
// return delta;
//}
void ExtensionRegistry::Link(const SmartPointer& extPoint, const QList& extensions)
{
extPoint->SetRawChildren(extensions);
registryObjects->Add(extPoint, true);
}
//QString ExtensionRegistry::RecordChange(const SmartPointer& extPoint, int extension, int kind)
//{
// // avoid computing deltas when there are no listeners
// if (listeners.isEmpty())
// return QString();
// ExtensionDelta extensionDelta = new ExtensionDelta();
// extensionDelta.setExtension(extension);
// extensionDelta.setExtensionPoint(extPoint.getObjectId());
// extensionDelta.setKind(kind);
// getDelta(extPoint.getNamespace()).addExtensionDelta(extensionDelta);
// return extPoint.getNamespace();
//}
//QString ExtensionRegistry::RecordChange(const SmartPointer& extPoint, const QList& extensions, int kind)
//{
// if (listeners.isEmpty())
// return null;
// QString namespace = extPoint.getNamespace();
// if (extensions == null || extensions.length == 0)
// return namespace;
// RegistryDelta pluginDelta = getDelta(extPoint.getNamespace());
// for (int i = 0; i < extensions.length; i++) {
// ExtensionDelta extensionDelta = new ExtensionDelta();
// extensionDelta.setExtension(extensions[i]);
// extensionDelta.setExtensionPoint(extPoint.getObjectId());
// extensionDelta.setKind(kind);
// pluginDelta.addExtensionDelta(extensionDelta);
// }
// return namespace;
//}
QString ExtensionRegistry::RemoveExtension(int extensionId)
{
Extension::Pointer extension = registryObjects->GetObject(extensionId, RegistryObjectManager::EXTENSION).Cast();
registryObjects->RemoveExtensionFromNamespaceIndex(extensionId, extension->GetNamespaceIdentifier());
QString xptName = extension->GetExtensionPointIdentifier();
ExtensionPoint::Pointer extPoint = registryObjects->GetExtensionPointObject(xptName);
if (extPoint.IsNull())
{
registryObjects->RemoveOrphan(xptName, extensionId);
return QString();
}
// otherwise, unlink the extension from the extension point
QList existingExtensions = extPoint->GetRawChildren();
QList newExtensions;
if (existingExtensions.size() > 1)
{
for (int i = 0; i < existingExtensions.size(); ++i)
if (existingExtensions[i] != extension->GetObjectId())
newExtensions.push_back(existingExtensions[i]);
}
Link(extPoint, newExtensions);
if (!eventDelta.IsNull())
eventDelta.RememberExtension(extPoint, extensionId);
return extPoint->GetNamespace();
//return recordChange(extPoint, extension.getObjectId(), IExtensionDelta.REMOVED);
}
QString ExtensionRegistry::RemoveExtensionPoint(int extPoint)
{
ExtensionPoint::Pointer extensionPoint = registryObjects->GetObject(
extPoint, RegistryObjectManager::EXTENSION_POINT).Cast();
registryObjects->RemoveExtensionPointFromNamespaceIndex(extPoint, extensionPoint->GetNamespace());
QList existingExtensions = extensionPoint->GetRawChildren();
if (!existingExtensions.empty())
{
registryObjects->AddOrphans(extensionPoint->GetUniqueIdentifier(), existingExtensions);
Link(extensionPoint, QList());
}
if (!eventDelta.IsNull())
{
eventDelta.RememberExtensionPoint(extensionPoint);
eventDelta.RememberExtensions(extensionPoint, existingExtensions);
}
return extensionPoint->GetNamespace();
//return recordChange(extensionPoint, existingExtensions, IExtensionDelta.REMOVED);
}
QSet ExtensionRegistry::RemoveExtensionsAndExtensionPoints(const QString& contributorId)
{
QSet affectedNamespaces;
QList extensions = registryObjects->GetExtensionsFrom(contributorId);
for (int i = 0; i < extensions.size(); i++)
{
QString namespaze = this->RemoveExtension(extensions[i]);
if (!namespaze.isEmpty())
affectedNamespaces.insert(namespaze);
}
// remove extension points
QList extPoints = registryObjects->GetExtensionPointsFrom(contributorId);
for (int i = 0; i < extPoints.size(); i++)
{
QString namespaze = this->RemoveExtensionPoint(extPoints[i]);
if (!namespaze.isEmpty())
affectedNamespaces.insert(namespaze);
}
return affectedNamespaces;
}
struct ExtensionRegistry::QueueElement
{
QList listenerInfos;
CombinedEventDelta scheduledDelta;
QueueElement()
{
}
QueueElement(const QList& infos, const CombinedEventDelta& delta)
: listenerInfos(infos), scheduledDelta(delta)
{
}
};
class ExtensionRegistry::RegistryEventThread : public QThread
{
private:
QAtomicInt stop;
ExtensionRegistry* registry;
Queue& queue;
public:
RegistryEventThread(ExtensionRegistry* registry, Queue& queue)
: stop(0), registry(registry), queue(queue)
{
this->setObjectName("Extension Registry Event Dispatcher");
}
void interrupt()
{
stop.fetchAndStoreOrdered(1);
}
void run() override
{
while (!stop.fetchAndAddOrdered(0))
{
QueueElement element;
{
Queue::Locker l(&queue);
while (queue.empty())
queue.wait();
element = queue.takeFirst();
}
registry->ProcessChangeEvent(element.listenerInfos, element.scheduledDelta);
}
}
};
bool ExtensionRegistry::CheckReadWriteAccess(QObject* key, bool persist) const
{
if (masterToken == key)
return true;
if (userToken == key && !persist)
return true;
return false;
}
void ExtensionRegistry::LogError(const QString& owner, const QString& contributionName, const ctkException& e)
{
QString message = QString("Could not parse XML contribution for \"%1\". Any contributed extensions "
"and extension points will be ignored.").arg(QString(owner) + "/" + contributionName);
IStatus::Pointer status(new Status(IStatus::ERROR_TYPE, RegistryMessages::OWNER_NAME, 0, message, e, BERRY_STATUS_LOC));
Log(status);
}
void ExtensionRegistry::CreateExtensionData(const QString& contributorId,
const ConfigurationElementDescription& description,
const SmartPointer& parent, bool persist)
{
ConfigurationElement::Pointer currentConfigurationElement = GetElementFactory()->CreateConfigurationElement(persist);
currentConfigurationElement->SetContributorId(contributorId);
currentConfigurationElement->SetName(description.GetName());
QList descriptionProperties = description.GetAttributes();
QList properties;
if (!descriptionProperties.empty())
{
for (int i = 0; i < descriptionProperties.size(); i++)
{
properties.push_back(descriptionProperties[i].GetName());
properties.push_back(Translate(descriptionProperties[i].GetValue(), nullptr));
}
}
currentConfigurationElement->SetProperties(properties);
QString value = description.GetValue();
if (!value.isEmpty())
currentConfigurationElement->SetValue(value);
GetObjectManager()->Add(currentConfigurationElement, true);
// process children
QList children = description.GetChildren();
if (!children.empty())
{
for (int i = 0; i < children.size(); i++)
{
CreateExtensionData(contributorId, children[i], currentConfigurationElement, persist);
}
}
QList newValues = parent->GetRawChildren();
newValues.push_back(currentConfigurationElement->GetObjectId());
parent->SetRawChildren(newValues);
currentConfigurationElement->SetParentId(parent->GetObjectId());
currentConfigurationElement->SetParentType(parent.Cast() ?
RegistryObjectManager::CONFIGURATION_ELEMENT :
RegistryObjectManager::EXTENSION);
}
bool ExtensionRegistry::RemoveObject(const SmartPointer& registryObject,
bool isExtensionPoint, QObject* token)
{
if (!CheckReadWriteAccess(token, registryObject->ShouldPersist()))
throw ctkInvalidArgumentException("Unauthorized access to the ExtensionRegistry.removeExtension() method. Check if proper access token is supplied.");
int id = registryObject->GetObjectId();
QWriteLocker l(&access);
eventDelta = CombinedEventDelta::RecordRemoval();
if (isExtensionPoint)
{
RemoveExtensionPoint(id);
}
else
{
RemoveExtension(id);
}
QHash removed;
removed.insert(id, registryObject);
// There is some asymmetry between extension and extension point removal. Removing extension point makes
// extensions "orphans" but does not remove them. As a result, only extensions needs to be processed.
if (!isExtensionPoint)
{
registryObjects->AddAssociatedObjects(removed, registryObject);
}
registryObjects->RemoveObjects(removed);
registryObjects->AddNavigableObjects(removed);
IObjectManager::Pointer manager = registryObjects->CreateDelegatingObjectManager(removed);
//GetDelta(namespaze)->SetObjectManager(manager);
//eventDelta->SetObjectManager(manager);
registryObjects->UnlinkChildFromContributions(id);
FireRegistryChangeEvent();
eventDelta.Reset();
return true;
}
void ExtensionRegistry::SetFileManager(const QString& /*cacheBase*/, bool /*isCacheReadOnly*/)
{
// if (cacheStorageManager != nullptr)
// cacheStorageManager->Close(); // close existing file manager first
// if (cacheBase != null) {
// cacheStorageManager = new StorageManager(cacheBase, isCacheReadOnly ? "none" : null, isCacheReadOnly); //$NON-NLS-1$
// try {
// cacheStorageManager.open(!isCacheReadOnly);
// } catch (IOException e) {
// // Ignore the exception. The registry will be rebuilt from source.
// }
// }
}
void ExtensionRegistry::EnterRead()
{
access.lockForRead();
}
void ExtensionRegistry::ExitRead()
{
access.unlock();
}
void ExtensionRegistry::SetElementFactory()
{
if (isMultiLanguage)
{
throw ctkRuntimeException("Multi-language registry not supported yet.");
//theRegistryObjectFactory = new RegistryObjectFactoryMulti(this);
}
else
{
theRegistryObjectFactory.reset(new RegistryObjectFactory(this));
}
}
//TableReader ExtensionRegistry::getTableReader() const
//{
// return theTableReader;
//}
bool ExtensionRegistry::CheckCache()
{
// for (int index = 0; index < strategy.getLocationsLength(); index++) {
// File possibleCacheLocation = strategy.getStorage(index);
// if (possibleCacheLocation == null)
// break; // bail out on the first null
// setFileManager(possibleCacheLocation, strategy.isCacheReadOnly(index));
// if (cacheStorageManager != null) {
// // check this new location:
// File cacheFile = null;
// try {
// cacheFile = cacheStorageManager.lookup(TableReader.getTestFileName(), false);
// } catch (IOException e) {
// //Ignore the exception. The registry will be rebuilt from the xml files.
// }
// if (cacheFile != null && cacheFile.isFile())
// return true; // found the appropriate location
// }
// }
return false;
}
void ExtensionRegistry::StopChangeEventScheduler()
{
if (!eventThread.isNull())
{
Queue::Locker l(&queue);
eventThread->interrupt();
eventThread->wait();
eventThread.reset();
}
}
SmartPointer ExtensionRegistry::GetObjectManager() const
{
return registryObjects;
}
void ExtensionRegistry::AddListener(IRegistryEventListener* listener, const QString& extensionPointId)
{
AddListenerInternal(listener, extensionPointId.isEmpty() ? IExtensionPointFilter(nullptr)
: IExtensionPointFilter(new SimpleExtensionPointFilter(extensionPointId)));
}
void ExtensionRegistry::AddListener(IRegistryEventListener* listener, const IExtensionPointFilter& filter)
{
this->AddListenerInternal(listener, filter);
}
QList > ExtensionRegistry::GetConfigurationElementsFor(const QString& extensionPointId) const
{
// this is just a convenience API - no need to do any sync'ing here
int lastdot = extensionPointId.lastIndexOf('.');
if (lastdot == -1)
{
QList();
}
return GetConfigurationElementsFor(extensionPointId.left(lastdot), extensionPointId.mid(lastdot + 1));
}
QList > ExtensionRegistry::GetConfigurationElementsFor(const QString& pluginId,
const QString& extensionPointSimpleId) const
{
// this is just a convenience API - no need to do any sync'ing here
IExtensionPoint::Pointer extPoint = this->GetExtensionPoint(pluginId, extensionPointSimpleId);
if (extPoint.IsNull())
return QList();
return extPoint->GetConfigurationElements();
}
QList > ExtensionRegistry::GetConfigurationElementsFor(const QString& pluginId,
const QString& extensionPointName,
const QString& extensionId) const
{
// this is just a convenience API - no need to do any sync'ing here
IExtension::Pointer extension = this->GetExtension(pluginId, extensionPointName, extensionId);
if (extension.IsNull())
return QList();
return extension->GetConfigurationElements();
}
SmartPointer ExtensionRegistry::GetExtension(const QString& extensionId) const
{
if (extensionId.isEmpty())
return IExtension::Pointer();
int lastdot = extensionId.lastIndexOf('.');
if (lastdot == -1)
return IExtension::Pointer();
QString namespaze = extensionId.left(lastdot);
QList extensions;
{
QReadLocker l(&access);
extensions = registryObjects->GetExtensionsFromNamespace(namespaze);
}
for (int i = 0; i < extensions.size(); i++)
{
ExtensionHandle::Pointer suspect = extensions[i];
if (extensionId == suspect->GetUniqueIdentifier())
return suspect;
}
return IExtension::Pointer();
}
SmartPointer ExtensionRegistry::GetExtension(const QString& extensionPointId, const QString& extensionId) const
{
// this is just a convenience API - no need to do any sync'ing here
int lastdot = extensionPointId.lastIndexOf('.');
if (lastdot == -1)
return IExtension::Pointer();
return GetExtension(extensionPointId.left(lastdot), extensionPointId.mid(lastdot + 1), extensionId);
}
SmartPointer ExtensionRegistry::GetExtension(const QString& pluginId,
const QString& extensionPointName,
const QString& extensionId) const
{
// this is just a convenience API - no need to do any sync'ing here
IExtensionPoint::Pointer extPoint = GetExtensionPoint(pluginId, extensionPointName);
if (extPoint.IsNotNull())
return extPoint->GetExtension(extensionId);
return IExtension::Pointer();
}
SmartPointer ExtensionRegistry::GetExtensionPoint(const QString& xptUniqueId) const
{
QReadLocker l(&access);
return registryObjects->GetExtensionPointHandle(xptUniqueId);
}
SmartPointer ExtensionRegistry::GetExtensionPoint(const QString& elementName, const QString& xpt) const
{
QReadLocker l(&access);
return registryObjects->GetExtensionPointHandle(elementName + '.' + xpt);
}
QList > ExtensionRegistry::GetExtensionPoints() const
{
QList handles;
{
QReadLocker l(&access);
handles = registryObjects->GetExtensionPointsHandles();
}
QList result;
foreach(ExtensionPointHandle::Pointer handle, handles)
{
result.push_back(handle);
}
return result;
}
QList > ExtensionRegistry::GetExtensionPoints(const QString& namespaceName) const
{
QList handles;
{
QReadLocker l(&access);
handles = registryObjects->GetExtensionPointsFromNamespace(namespaceName);
}
QList result;
foreach(ExtensionPointHandle::Pointer handle, handles)
{
result.push_back(handle);
}
return result;
}
QList > ExtensionRegistry::GetExtensions(const QString& namespaceName) const
{
QList handles;
{
QReadLocker l(&access);
handles = registryObjects->GetExtensionsFromNamespace(namespaceName);
}
QList result;
foreach (ExtensionHandle::Pointer handle, handles)
{
result.push_back(handle);
}
return result;
}
QList > ExtensionRegistry::GetExtensions(const SmartPointer& contributor) const
{
RegistryContributor::Pointer regContributor = contributor.Cast();
if (regContributor.IsNull())
throw ctkInvalidArgumentException("Contributor must be a RegistryContributor."); // should never happen
QString contributorId = regContributor->GetActualId();
QList handles;
{
QReadLocker l(&access);
handles = registryObjects->GetExtensionsFromContributor(contributorId);
}
QList result;
foreach (ExtensionHandle::Pointer handle, handles)
{
result.push_back(handle);
}
return result;
}
QList > ExtensionRegistry::GetExtensionPoints(const SmartPointer& contributor) const
{
RegistryContributor::Pointer regContributor = contributor.Cast();
if (regContributor.IsNull())
throw ctkInvalidArgumentException("Contributor must be a RegistryContributor."); // should never happen
QString contributorId = regContributor->GetActualId();
QList handles;
{
QReadLocker l(&access);
handles = registryObjects->GetExtensionPointsFromContributor(contributorId);
}
QList result;
foreach (ExtensionPointHandle::Pointer handle, handles)
{
result.push_back(handle);
}
return result;
}
QList ExtensionRegistry::GetNamespaces() const
{
QReadLocker l(&access);
QList namespaceElements = registryObjects->GetNamespacesIndex().Elements();
QList namespaceNames;
for (int i = 0; i < namespaceElements.size(); i++)
{
namespaceNames.push_back(namespaceElements[i]->GetKey());
}
return namespaceNames;
}
bool ExtensionRegistry::HasContributor(const SmartPointer& contributor) const
{
RegistryContributor::Pointer regContributor = contributor.Cast();
if (regContributor.IsNull())
throw ctkInvalidArgumentException("Contributor must be a RegistryContributor."); // should never happen
QString contributorId = regContributor->GetActualId();
return HasContributor(contributorId);
}
bool ExtensionRegistry::HasContributor(const QString& contributorId) const
{
QReadLocker l(&access);
return registryObjects->HasContribution(contributorId);
}
void ExtensionRegistry::Remove(const QString& removedContributorId, long timestamp)
{
Remove(removedContributorId);
if (timestamp != 0)
aggregatedTimestamp.Remove(timestamp);
}
void ExtensionRegistry::RemoveContributor(const SmartPointer& contributor, QObject* key)
{
RegistryContributor::Pointer regContributor = contributor.Cast();
if (regContributor.IsNull())
throw ctkInvalidArgumentException("Contributor must be a RegistryContributor."); // should never happen
if (!CheckReadWriteAccess(key, true))
throw ctkInvalidArgumentException("Unauthorized access to the ExtensionRegistry.removeContributor() method. Check if proper access token is supplied.");
QString contributorId = regContributor->GetActualId();
Remove(contributorId);
}
void ExtensionRegistry::Remove(const QString& removedContributorId)
{
QWriteLocker l(&access);
eventDelta = CombinedEventDelta::RecordRemoval();
BasicRemove(removedContributorId);
FireRegistryChangeEvent();
eventDelta.Reset();
}
void ExtensionRegistry::RemoveListener(IRegistryEventListener* listener)
{
listeners.Remove(ListenerInfo(listener, IExtensionPointFilter(nullptr)));
}
ExtensionRegistry::ExtensionRegistry(RegistryStrategy* registryStrategy, QObject* masterToken, QObject* userToken)
: registryObjects(nullptr), isMultiLanguage(false), mlErrorLogged(false), eventThread(nullptr)
{
isMultiLanguage = RegistryProperties::GetProperty(RegistryConstants::PROP_REGISTRY_MULTI_LANGUAGE) == "true";
if (registryStrategy != nullptr)
strategy.reset(registryStrategy);
else
strategy.reset(new RegistryStrategy(QList(), QList(), nullptr));
this->masterToken = masterToken;
this->userToken = userToken;
registryObjects = new RegistryObjectManager(this);
bool isRegistryFilledFromCache = false; // indicates if registry was able to use cache to populate it's content
if (strategy->CacheUse())
{
// Try to read the registry from the cache first. If that fails, create a new registry
QTime timer;
if (Debug())
timer.start();
//The cache is made of several files, find the real names of these other files. If all files are found, try to initialize the objectManager
if (CheckCache())
{
// TODO Registry Cache
// try {
// theTableReader.setTableFile(cacheStorageManager.lookup(TableReader.TABLE, false));
// theTableReader.setExtraDataFile(cacheStorageManager.lookup(TableReader.EXTRA, false));
// theTableReader.setMainDataFile(cacheStorageManager.lookup(TableReader.MAIN, false));
// theTableReader.setContributionsFile(cacheStorageManager.lookup(TableReader.CONTRIBUTIONS, false));
// theTableReader.setContributorsFile(cacheStorageManager.lookup(TableReader.CONTRIBUTORS, false));
// theTableReader.setNamespacesFile(cacheStorageManager.lookup(TableReader.NAMESPACES, false));
// theTableReader.setOrphansFile(cacheStorageManager.lookup(TableReader.ORPHANS, false));
// long timestamp = strategy.getContributionsTimestamp();
// isRegistryFilledFromCache = registryObjects.init(timestamp);
// if (isRegistryFilledFromCache)
// aggregatedTimestamp.set(timestamp);
// } catch (IOException e) {
// // The registry will be rebuilt from the xml files. Make sure to clear anything filled
// // from cache so that we won't have partially filled items.
// isRegistryFilledFromCache = false;
// clearRegistryCache();
// log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, 0, RegistryMessages.registry_bad_cache, e));
// }
}
// if (!isRegistryFilledFromCache)
// {
// // set cache storage manager to a first writable location
// for (int index = 0; index < strategy.getLocationsLength(); index++) {
// if (!strategy.isCacheReadOnly(index)) {
// setFileManager(strategy.getStorage(index), false);
// break;
// }
// }
// }
if (Debug() && isRegistryFilledFromCache)
BERRY_INFO << "Reading registry cache: " << timer.elapsed() << "ms";
if (Debug())
{
if (!isRegistryFilledFromCache)
BERRY_INFO << "Reloading registry from manifest files...";
else
BERRY_INFO << "Using registry cache...";
}
}
if (DebugEvents())
{
struct DebugRegistryListener : public IRegistryEventListener
{
void Added(const QList& extensions) override
{
BERRY_INFO << "Registry extensions ADDED:";
foreach(IExtension::Pointer extension, extensions)
{
BERRY_INFO << "\t" << extension->GetExtensionPointUniqueIdentifier() << " - "
<< extension->GetNamespaceIdentifier() << "." << extension->GetSimpleIdentifier();
}
}
void Removed(const QList& extensions) override
{
BERRY_INFO << "Registry extensions REMOVED:";
foreach(IExtension::Pointer extension, extensions)
{
BERRY_INFO << "\t" << extension->GetExtensionPointUniqueIdentifier() << " - "
<< extension->GetNamespaceIdentifier() << "." << extension->GetSimpleIdentifier();
}
}
void Added(const QList& extensionPoints) override
{
BERRY_INFO << "Registry extension-points ADDED:";
foreach(IExtensionPoint::Pointer extensionPoint, extensionPoints)
{
BERRY_INFO << "\t" << extensionPoint->GetUniqueIdentifier();
}
}
void Removed(const QList& extensionPoints) override
{
BERRY_INFO << "Registry extension-points REMOVED:";
foreach(IExtensionPoint::Pointer extensionPoint, extensionPoints)
{
BERRY_INFO << "\t" << extensionPoint->GetUniqueIdentifier();
}
}
};
debugRegistryListener.reset(new DebugRegistryListener());
AddListener(debugRegistryListener.data());
}
// Do extra start processing if specified in the registry strategy
strategy->OnStart(this, isRegistryFilledFromCache);
}
ExtensionRegistry::~ExtensionRegistry()
{
}
void ExtensionRegistry::Stop(QObject* /*key*/)
{
// If the registry creator specified a key token, check that the key mathches it
- // (it is assumed that registry owner keeps the key to prevent unautorized accesss).
+ // (it is assumed that registry owner keeps the key to prevent unautorized access).
if (masterToken != nullptr && masterToken != nullptr)
{
throw ctkInvalidArgumentException("Unauthorized access to the ExtensionRegistry.stop() method. Check if proper access token is supplied."); //$NON-NLS-1$
}
// Do extra stop processing if specified in the registry strategy
strategy->OnStop(this);
StopChangeEventScheduler();
// if (cacheStorageManager == nullptr)
// return;
// if (!registryObjects.isDirty() || cacheStorageManager.isReadOnly()) {
// cacheStorageManager.close();
// theTableReader.close();
// return;
// }
// File tableFile = null;
// File mainFile = null;
// File extraFile = null;
// File contributionsFile = null;
// File contributorsFile = null;
// File namespacesFile = null;
// File orphansFile = null;
// TableWriter theTableWriter = new TableWriter(this);
// try {
// cacheStorageManager.lookup(TableReader.TABLE, true);
// cacheStorageManager.lookup(TableReader.MAIN, true);
// cacheStorageManager.lookup(TableReader.EXTRA, true);
// cacheStorageManager.lookup(TableReader.CONTRIBUTIONS, true);
// cacheStorageManager.lookup(TableReader.CONTRIBUTORS, true);
// cacheStorageManager.lookup(TableReader.NAMESPACES, true);
// cacheStorageManager.lookup(TableReader.ORPHANS, true);
// tableFile = File.createTempFile(TableReader.TABLE, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$
// mainFile = File.createTempFile(TableReader.MAIN, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$
// extraFile = File.createTempFile(TableReader.EXTRA, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$
// contributionsFile = File.createTempFile(TableReader.CONTRIBUTIONS, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$
// contributorsFile = File.createTempFile(TableReader.CONTRIBUTORS, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$
// namespacesFile = File.createTempFile(TableReader.NAMESPACES, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$
// orphansFile = File.createTempFile(TableReader.ORPHANS, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$
// theTableWriter.setTableFile(tableFile);
// theTableWriter.setExtraDataFile(extraFile);
// theTableWriter.setMainDataFile(mainFile);
// theTableWriter.setContributionsFile(contributionsFile);
// theTableWriter.setContributorsFile(contributorsFile);
// theTableWriter.setNamespacesFile(namespacesFile);
// theTableWriter.setOrphansFile(orphansFile);
// } catch (IOException e) {
// cacheStorageManager.close();
// return; //Ignore the exception since we can recompute the cache
// }
// try {
// long timestamp;
// // A bit of backward compatibility: if registry was modified, but timestamp was not,
// // it means that the new timestamp tracking mechanism was not used. In this case
// // explicitly obtain timestamps for all contributions. Note that this logic
// // maintains a problem described in the bug 104267 for contributions that
// // don't use the timestamp tracking mechanism.
// if (aggregatedTimestamp.isModifed())
// timestamp = aggregatedTimestamp.getContentsTimestamp(); // use timestamp tracking
// else
// timestamp = strategy.getContributionsTimestamp(); // use legacy approach
// if (theTableWriter.saveCache(registryObjects, timestamp))
// cacheStorageManager.update(new QString[] {TableReader.TABLE, TableReader.MAIN, TableReader.EXTRA, TableReader.CONTRIBUTIONS, TableReader.CONTRIBUTORS, TableReader.NAMESPACES, TableReader.ORPHANS}, new QString[] {tableFile.getName(), mainFile.getName(), extraFile.getName(), contributionsFile.getName(), contributorsFile.getName(), namespacesFile.getName(), orphansFile.getName()});
// } catch (IOException e) {
// //Ignore the exception since we can recompute the cache
// }
// theTableReader.close();
// cacheStorageManager.close();
}
void ExtensionRegistry::ClearRegistryCache()
{
// QString[] keys = new QString[] {TableReader.TABLE, TableReader.MAIN, TableReader.EXTRA, TableReader.CONTRIBUTIONS, TableReader.ORPHANS};
// for (int i = 0; i < keys.length; i++)
// try {
// cacheStorageManager.remove(keys[i]);
// } catch (IOException e) {
// log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, IStatus.ERROR, RegistryMessages.meta_registryCacheReadProblems, e));
// }
aggregatedTimestamp.Reset();
}
RegistryObjectFactory* ExtensionRegistry::GetElementFactory()
{
if (theRegistryObjectFactory.isNull())
SetElementFactory();
return theRegistryObjectFactory.data();
}
void ExtensionRegistry::Log(const SmartPointer& status) const
{
strategy->Log(status);
}
QString ExtensionRegistry::Translate(const QString& key, QTranslator* resources) const
{
if (isMultiLanguage)
return key;
return strategy->Translate(key, resources);
}
bool ExtensionRegistry::Debug() const
{
return strategy->Debug();
}
bool ExtensionRegistry::DebugEvents() const
{
return strategy->DebugRegistryEvents();
}
bool ExtensionRegistry::UseLazyCacheLoading() const
{
return strategy->CacheLazyLoading();
}
long ExtensionRegistry::ComputeState() const
{
return strategy->GetContainerTimestamp();
}
QObject* ExtensionRegistry::CreateExecutableExtension(const SmartPointer& defaultContributor,
const QString& className, const QString& requestedContributorName)
{
return strategy->CreateExecutableExtension(defaultContributor, className, requestedContributorName);
}
void ExtensionRegistry::ProcessChangeEvent(
const QList& listenerInfos, const CombinedEventDelta& scheduledDelta)
{
for (int i = 0; i < listenerInfos.size(); i++)
{
const ListenerInfo& listenerInfo = listenerInfos[i];
IRegistryEventListener* extensionListener = listenerInfo.listener;
QList extensions = scheduledDelta.GetExtensions(listenerInfo.filter);
QList extensionPoints = scheduledDelta.GetExtensionPoints(listenerInfo.filter);
// notification order - on addition: extension points; then extensions
if (scheduledDelta.IsAddition())
{
if (!extensionPoints.empty())
extensionListener->Added(extensionPoints);
if (!extensions.empty())
extensionListener->Added(extensions);
}
else
{ // on removal: extensions; then extension points
if (!extensions.empty())
extensionListener->Removed(extensions);
if (!extensionPoints.empty())
extensionListener->Removed(extensionPoints);
}
}
IObjectManager::Pointer manager = scheduledDelta.GetObjectManager();
if (manager.IsNotNull())
manager->Close();
}
void ExtensionRegistry::ScheduleChangeEvent(const QList& listenerInfos,
const CombinedEventDelta& scheduledDelta)
{
QueueElement newElement(listenerInfos, scheduledDelta);
if (eventThread.isNull())
{
eventThread.reset(new RegistryEventThread(this, queue));
eventThread->start();
}
{
Queue::Locker l(&queue);
queue.push_back(newElement);
queue.notify();
}
}
bool ExtensionRegistry::AddContribution(QIODevice* is, const SmartPointer& contributor,
bool persist, const QString& contributionName,
QTranslator* translationBundle, QObject* key, long timestamp)
{
bool result = AddContribution(is, contributor, persist, contributionName, translationBundle, key);
if (timestamp != 0)
aggregatedTimestamp.Add(timestamp);
return result;
}
bool ExtensionRegistry::AddContribution(QIODevice* is, const SmartPointer& contributor, bool persist,
const QString& contributionName, QTranslator* translationBundle, QObject* key)
{
if (!CheckReadWriteAccess(key, persist))
throw ctkInvalidArgumentException("Unauthorized access to the ExtensionRegistry::AddContribution() method. Check if proper access token is supplied.");
RegistryContributor::Pointer internalContributor = contributor.Cast();
registryObjects->AddContributor(internalContributor); // only adds a contributor if it is not already present
QString ownerName = internalContributor->GetActualName();
QString message = QString("Problems parsing plug-in manifest for: \"%1\".").arg(ownerName);
MultiStatus::Pointer problems(new MultiStatus(RegistryMessages::OWNER_NAME,
ExtensionsParser::PARSE_PROBLEM, message, BERRY_STATUS_LOC));
ExtensionsParser parser(problems, this);
RegistryContribution::Pointer contribution =
GetElementFactory()->CreateContribution(internalContributor->GetActualId(), persist);
try
{
QXmlInputSource xmlInput(is);
bool success = parser.parseManifest(strategy->GetXMLParser(), &xmlInput, contributionName,
GetObjectManager().GetPointer(), contribution, translationBundle);
int status = problems->GetSeverity();
if (status != IStatus::OK_TYPE || !success)
{
Log(problems);
if (status == IStatus::ERROR_TYPE || status == IStatus::CANCEL_TYPE || !success)
return false;
}
}
catch (const ctkException& e)
{
LogError(ownerName, contributionName, e);
return false;
}
Add(contribution); // the add() method does synchronization
return true;
}
bool ExtensionRegistry::AddExtensionPoint(const QString& identifier, const SmartPointer& contributor,
bool persist, const QString& label, const QString& schemaReference, QObject* token)
{
if (!CheckReadWriteAccess(token, persist))
throw ctkInvalidArgumentException("Unauthorized access to the ExtensionRegistry::AddExtensionPoint() method. Check if proper access token is supplied.");
RegistryContributor::Pointer internalContributor = contributor.Cast();
registryObjects->AddContributor(internalContributor); // only adds a contributor if it is not already present
QString contributorId = internalContributor->GetActualId();
// Extension point Id might not be null
if (identifier.isEmpty())
{
QString message = QString("Missing ID for the extension point \"%1\". Element ignored.").arg(label);
IStatus::Pointer status(new Status(IStatus::ERROR_TYPE, RegistryMessages::OWNER_NAME, 0, message, BERRY_STATUS_LOC));
Log(status);
}
// addition wraps in a contribution
RegistryContribution::Pointer contribution = GetElementFactory()->CreateContribution(contributorId, persist);
ExtensionPoint::Pointer currentExtPoint = GetElementFactory()->CreateExtensionPoint(persist);
QString uniqueId;
QString namespaceName;
int simpleIdStart = identifier.lastIndexOf('.');
if (simpleIdStart == -1)
{
namespaceName = contribution->GetDefaultNamespace();
uniqueId = namespaceName + '.' + identifier;
}
else
{
namespaceName = identifier.left(simpleIdStart);
uniqueId = identifier;
}
currentExtPoint->SetUniqueIdentifier(uniqueId);
currentExtPoint->SetNamespace(namespaceName);
QString labelNLS = Translate(label, nullptr);
currentExtPoint->SetLabel(labelNLS);
currentExtPoint->SetSchema(schemaReference);
if (!GetObjectManager()->AddExtensionPoint(currentExtPoint, true))
{
if (Debug())
{
QString msg = QString("Ignored duplicate extension point \"%1\" supplied by \"%2\".").arg(uniqueId).arg(contribution->GetDefaultNamespace());
IStatus::Pointer status(new Status(IStatus::ERROR_TYPE, RegistryMessages::OWNER_NAME, 0, msg, BERRY_STATUS_LOC));
Log(status);
}
return false;
}
currentExtPoint->SetContributorId(contributorId);
// array format: {Number of extension points, Number of extensions, Extension Id}
QList contributionChildren;
// Put the extension points into this namespace
contributionChildren.push_back(1);
contributionChildren.push_back(0);
contributionChildren.push_back(currentExtPoint->GetObjectId());
contribution->SetRawChildren(contributionChildren);
Add(contribution);
return true;
}
bool ExtensionRegistry::AddExtension(const QString& identifier, const SmartPointer& contributor,
bool persist, const QString& label, const QString& extensionPointId,
const ConfigurationElementDescription& configurationElements, QObject* token)
{
if (!CheckReadWriteAccess(token, persist))
throw ctkInvalidArgumentException("Unauthorized access to the ExtensionRegistry::AddExtensionPoint() method. Check if proper access token is supplied.");
// prepare namespace information
RegistryContributor::Pointer internalContributor = contributor.Cast();
registryObjects->AddContributor(internalContributor); // only adds a contributor if it is not already present
QString contributorId = internalContributor->GetActualId();
// addition wraps in a contribution
RegistryContribution::Pointer contribution = GetElementFactory()->CreateContribution(contributorId, persist);
Extension::Pointer currentExtension = GetElementFactory()->CreateExtension(persist);
QString simpleId;
QString namespaceName;
int simpleIdStart = identifier.lastIndexOf('.');
if (simpleIdStart != -1)
{
simpleId = identifier.mid(simpleIdStart + 1);
namespaceName = identifier.left(simpleIdStart);
}
else
{
simpleId = identifier;
namespaceName = contribution->GetDefaultNamespace();
}
currentExtension->SetSimpleIdentifier(simpleId);
currentExtension->SetNamespaceIdentifier(namespaceName);
QString extensionLabelNLS = Translate(label, nullptr);
currentExtension->SetLabel(extensionLabelNLS);
QString targetExtensionPointId;
if (extensionPointId.indexOf('.') == -1) // No dots -> namespace name added at the start
targetExtensionPointId = contribution->GetDefaultNamespace() + '.' + extensionPointId;
else
targetExtensionPointId = extensionPointId;
currentExtension->SetExtensionPointIdentifier(targetExtensionPointId);
// if we have an Id specified, check for duplicates. Only issue warning if duplicate found
// as it might still work fine - depending on the access pattern.
if (!simpleId.isNull() && Debug())
{
QString uniqueId = namespaceName + '.' + simpleId;
IExtension::Pointer existingExtension = GetExtension(uniqueId);
if (existingExtension.IsNotNull())
{
QString currentSupplier = contribution->GetDefaultNamespace();
QString existingSupplier = existingExtension->GetContributor()->GetName();
QString msg = QString("Extensions supplied by \"%1\" and \"%2\" have the same Id: \"%3\".")
.arg(currentSupplier).arg(existingSupplier).arg(uniqueId);
IStatus::Pointer status(new Status(IStatus::WARNING_TYPE, RegistryMessages::OWNER_NAME, 0, msg, BERRY_STATUS_LOC));
Log(status);
return false;
}
}
GetObjectManager()->Add(currentExtension, true);
CreateExtensionData(contributorId, configurationElements, currentExtension, persist);
currentExtension->SetContributorId(contributorId);
QList contributionChildren;
contributionChildren.push_back(0);
contributionChildren.push_back(1);
contributionChildren.push_back(currentExtension->GetObjectId());
contribution->SetRawChildren(contributionChildren);
Add(contribution);
return true;
}
bool ExtensionRegistry::RemoveExtension(const SmartPointer& extension, QObject* token)
{
ExtensionHandle::Pointer handle = extension.Cast();
if (handle.IsNull())
return false;
return RemoveObject(handle->GetObject(), false, token);
}
bool ExtensionRegistry::RemoveExtensionPoint(const SmartPointer& extensionPoint, QObject* token)
{
ExtensionPointHandle::Pointer handle = extensionPoint.Cast();
if (handle.IsNull())
return false;
return RemoveObject(handle->GetObject(), true, token);
}
QList > ExtensionRegistry::GetAllContributors() const
{
QList result;
QReadLocker l(&access);
foreach(RegistryContributor::Pointer contributor, registryObjects->GetContributors().values())
{
result.push_back(contributor);
}
return result;
}
bool ExtensionRegistry::IsMultiLanguage() const
{
return isMultiLanguage;
}
QList ExtensionRegistry::Translate(const QList& nonTranslated, const SmartPointer& contributor,
const QLocale& locale) const
{
return strategy->Translate(nonTranslated, contributor, locale);
}
QLocale ExtensionRegistry::GetLocale() const
{
return strategy->GetLocale();
}
void ExtensionRegistry::LogMultiLangError() const
{
if (mlErrorLogged) // only log this error ones
return;
IStatus::Pointer status(new Status(IStatus::ERROR_TYPE, RegistryMessages::OWNER_NAME, 0,
QString("The requested multi-language operation is not enabled. See runtime option \"")
+ RegistryConstants::PROP_REGISTRY_MULTI_LANGUAGE + "\".", ctkInvalidArgumentException(""), BERRY_STATUS_LOC));
Log(status);
mlErrorLogged = true;
}
}
diff --git a/Plugins/org.blueberry.core.runtime/src/internal/berryRegistryContributor.h b/Plugins/org.blueberry.core.runtime/src/internal/berryRegistryContributor.h
index 2e27c93a20..2ffe88e19b 100644
--- a/Plugins/org.blueberry.core.runtime/src/internal/berryRegistryContributor.h
+++ b/Plugins/org.blueberry.core.runtime/src/internal/berryRegistryContributor.h
@@ -1,139 +1,139 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef BERRYREGISTRYCONTRIBUTOR_H
#define BERRYREGISTRYCONTRIBUTOR_H
#include "berryIContributor.h"
namespace berry {
/**
* This class describes a registry contributor which is an entity that supplies information
* to the extension registry. Depending on the registry strategy, contributor might delegate
* some of its functionality to a "host" contributor. For instance, OSGi registry strategy
* uses "host" contributor to delegate some functionality from fragments to plug-ins.
*
* This class can be instantiated by the registry Service Providers.
*
* This class is not intended to be extended.
*
* Note: This class/interface is part of an interim API that is still under
* development and expected to change significantly before reaching stability.
* It is being made available at this early stage to solicit feedback from pioneering
* adopters on the understanding that any code that uses this API will almost certainly
* be broken (repeatedly) as the API evolves.
*
* @noextend This class is not intended to be subclassed by clients.
*/
class RegistryContributor : public IContributor
{
private:
/**
* Actual ID of the contributor (e.g., "12"). IDs are expected to be unique in the workspace.
*/
QString actualContributorId;
/**
* Actual name of the contributor (e.g., "org.eclipse.core.runtime.fragment").
*/
QString actualContributorName;
/**
* ID associated with the entity "in charge" of the contributor (e.g., "1"). IDs are expected
* to be unique in the workspace. If contributor does not rely on a host, this value should be
* the same as the actual contributor ID.
*/
QString hostId;
/**
* Name of the entity "in charge" of the contributor (e.g. "org.eclipse.core.runtime").
* If contributor does not rely on a host, this value should be the same as the actual
* contributor name.
*/
QString hostName;
public:
berryObjectMacro(berry::RegistryContributor);
/**
* Constructor for the registry contributor.
*
* The actual ID is a string identifier for the contributor (e.g., "12") and is expected
* to be unique within the workspace. The actual ID of the contributor must not
* be null
.
*
* The actual name is the name associated with the contributor
* (e.g., "org.eclipse.core.runtime.fragment"). The actual name of the contributor must
* not be null
.
*
* The host ID is the identifier associated with the entity "in charge" of the contributor
* (e.g., "1"). IDs are expected to be unique in the workspace. If contributor does not
* rely on a host, then null
should be used as the host ID.
*
* The host name is the name of the entity "in charge" of the contributor
* (e.g., "org.eclipse.core.runtime"). If contributor does not rely on a host, then
* null
should be used as the host name.
*
- * There should be 1-to-1 mapping between the contributor and the contibutor ID.
+ * There should be 1-to-1 mapping between the contributor and the contributor ID.
* The IDs (either actual or host) can not be re-used in the same registry.
* For example, if ID of 12 was used to identify contributorA, the ID of 12 can not
* be used to identify contributorB or a host for the contributorC.
*
* @param actualId contributor identifier
* @param actualName name of the contributor
* @param hostId id associated with the host, or null
* @param hostName name of the host, or null
*/
RegistryContributor(const QString& actualId, const QString& actualName,
const QString& hostId, const QString& hostName);
/**
* Provides actual ID associated with the registry contributor (e.g., "12"). IDs are expected
* to be unique in the workspace.
*
* @return actual ID of the registry contributor
*/
QString GetActualId() const;
/**
* Provides actual name of the registry contributor (e.g., "org.eclipe.core.runtime.fragment").
*
* @return actual name of the registry contributor
*/
QString GetActualName() const;
/**
* Provides ID associated with the entity "in charge" of the contributor (e.g., "1"). IDs are expected
* to be unique in the workspace. If contributor does not rely on a host, this value should be
* the same as the actual contributor ID.
*
* @return id of the registry contributor
*/
QString GetId() const;
/**
* Provides name of the entity "in charge" of the contributor (e.g., "org.eclipse.core.runtime").
* If contributor does not rely on a host, this value should be the same as the actual contributor name.
*
* @return name of the registry contributor
*/
QString GetName() const override;
};
}
#endif // BERRYREGISTRYCONTRIBUTOR_H
diff --git a/Plugins/org.blueberry.core.runtime/src/internal/berryRegistryObject.cpp b/Plugins/org.blueberry.core.runtime/src/internal/berryRegistryObject.cpp
index 3a5f23ef26..402bf7a6ed 100644
--- a/Plugins/org.blueberry.core.runtime/src/internal/berryRegistryObject.cpp
+++ b/Plugins/org.blueberry.core.runtime/src/internal/berryRegistryObject.cpp
@@ -1,119 +1,119 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include "berryRegistryObject.h"
#include "berryExtensionRegistry.h"
#include "berryRegistryObjectManager.h"
namespace berry {
// it is assumed that int has 32 bits (bits #0 to #31);
// bits #0 - #29 are the offset (limited to about 1Gb)
-// bit #30 - persistance flag
+// bit #30 - persistence flag
// bit #31 - registry object has no extra data offset
// the bit#31 is a sign bit; bit#30 is the highest mantissa bit
const int RegistryObject::EMPTY_MASK = 0x80000000; // only taking bit #31
const int RegistryObject::PERSIST_MASK = 0x40000000; // only taking bit #30
const int RegistryObject::OFFSET_MASK = 0x3FFFFFFF; // all bits but #30, #31
RegistryObject::RegistryObject()
: registry(nullptr), objectId(RegistryObjectManager::UNKNOWN), extraDataOffset(EMPTY_MASK)
{
objectKey = QString::number(objectId);
}
QString RegistryObject::GetKey() const
{
return objectKey;
}
bool RegistryObject::IsEqual(const KeyedElement& other) const
{
return objectId == static_cast(other).objectId;
}
RegistryObject::RegistryObject(ExtensionRegistry* registry, bool persist)
: registry(registry), objectId(RegistryObjectManager::UNKNOWN), extraDataOffset(EMPTY_MASK)
{
objectKey = QString::number(objectId);
SetPersist(persist);
}
void RegistryObject::SetRawChildren(const QList& values)
{
children = values;
}
QList RegistryObject::GetRawChildren() const
{
return children;
}
void RegistryObject::SetObjectId(int value)
{
objectId = value;
objectKey = QString::number(value);
}
int RegistryObject::GetObjectId() const
{
return objectId;
}
bool RegistryObject::ShouldPersist() const
{
return (extraDataOffset & PERSIST_MASK) == PERSIST_MASK;
}
bool RegistryObject::NoExtraData() const
{
return (extraDataOffset & EMPTY_MASK) == EMPTY_MASK;
}
int RegistryObject::GetExtraDataOffset() const
{
if (NoExtraData())
return -1;
return extraDataOffset & OFFSET_MASK;
}
void RegistryObject::SetExtraDataOffset(int offset)
{
if (offset == -1)
{
extraDataOffset &= ~OFFSET_MASK; // clear all offset bits
extraDataOffset |= EMPTY_MASK;
return;
}
if ((offset & OFFSET_MASK) != offset)
throw ctkInvalidArgumentException("Registry object: extra data offset is out of range");
extraDataOffset &= ~(OFFSET_MASK | EMPTY_MASK); // clear all offset bits; mark as non-empty
extraDataOffset |= (offset & OFFSET_MASK); // set all offset bits
}
QLocale RegistryObject::GetLocale() const
{
return registry->GetLocale();
}
void RegistryObject::SetPersist(bool persist)
{
if (persist)
extraDataOffset |= PERSIST_MASK;
else
extraDataOffset &= ~PERSIST_MASK;
}
}
diff --git a/Plugins/org.blueberry.core.runtime/src/internal/berryRegistryObject.h b/Plugins/org.blueberry.core.runtime/src/internal/berryRegistryObject.h
index 2158df3d03..aecc42ad76 100644
--- a/Plugins/org.blueberry.core.runtime/src/internal/berryRegistryObject.h
+++ b/Plugins/org.blueberry.core.runtime/src/internal/berryRegistryObject.h
@@ -1,98 +1,98 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef BERRYREGISTRYOBJECT_H
#define BERRYREGISTRYOBJECT_H
#include "berryKeyedElement.h"
namespace berry {
class ExtensionRegistry;
/**
* An object which has the general characteristics of all the nestable elements
* in a plug-in manifest.
*/
class RegistryObject : public KeyedElement
{
public:
berryObjectMacro(berry::RegistryObject);
RegistryObject();
//Implementation of the KeyedElement interface
QString GetKey() const override;
int GetObjectId() const;
//This can not return null. It returns the singleton empty array or an array
QList GetRawChildren() const;
bool NoExtraData() const;
protected:
friend class RegistryObjectManager;
friend class ExtensionRegistry;
friend class ExtensionsParser;
QList children;
// it is assumed that int has 32 bits (bits #0 to #31);
// bits #0 - #29 are the offset (limited to about 1Gb)
- // bit #30 - persistance flag
+ // bit #30 - persistence flag
// bit #31 - registry object has no extra data offset
// the bit#31 is a sign bit; bit#30 is the highest mantissa bit
static const int EMPTY_MASK; // = 0x80000000; // only taking bit #31
static const int PERSIST_MASK; // = 0x40000000; // only taking bit #30
static const int OFFSET_MASK; // = 0x3FFFFFFF; // all bits but #30, #31
//The registry that owns this object
ExtensionRegistry* registry;
RegistryObject(ExtensionRegistry* registry, bool persist);
void SetRawChildren(const QList& values);
void SetObjectId(int value);
bool ShouldPersist() const;
// Convert no extra data to -1 on output
int GetExtraDataOffset() const;
// Accept -1 as "no extra data" on input
void SetExtraDataOffset(int offset);
QLocale GetLocale() const;
private:
//Object identifier
uint objectId; // = RegistryObjectManager::UNKNOWN;
// The key
QString objectKey;
// The field combines offset, persistence flag, and no offset flag
int extraDataOffset; // = EMPTY_MASK;
void SetPersist(bool persist);
bool IsEqual(const KeyedElement& other) const override;
};
}
#endif // BERRYREGISTRYOBJECT_H
diff --git a/Plugins/org.blueberry.core.runtime/src/internal/berryRegistryObjectManager.h b/Plugins/org.blueberry.core.runtime/src/internal/berryRegistryObjectManager.h
index f962c2496f..566231a86a 100644
--- a/Plugins/org.blueberry.core.runtime/src/internal/berryRegistryObjectManager.h
+++ b/Plugins/org.blueberry.core.runtime/src/internal/berryRegistryObjectManager.h
@@ -1,281 +1,281 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef BERRYREGISTRYOBJECTMANAGER_H
#define BERRYREGISTRYOBJECTMANAGER_H
#include "berryIObjectManager.h"
#include "berryHashtableOfStringAndInt.h"
#include "berryKeyedHashSet.h"
#include
namespace berry {
class ExtensionHandle;
class ExtensionPoint;
class ExtensionPointHandle;
class ExtensionRegistry;
class RegistryContribution;
class RegistryContributor;
class RegistryIndexElement;
class RegistryObject;
class RegistryObjectReferenceMap;
/**
* This class manage all the object from the registry but does not deal with their dependencies.
* It serves the objects which are either directly obtained from memory or read from a cache.
* It also returns handles for objects.
*/
class RegistryObjectManager : public IObjectManager
{
public:
berryObjectMacro(berry::RegistryObjectManager);
//Constants used to get the objects and their handles
enum Type {
CONFIGURATION_ELEMENT = 1,
EXTENSION,
EXTENSION_POINT,
THIRDLEVEL_CONFIGURATION_ELEMENT
};
RegistryObjectManager(ExtensionRegistry* registry);
~RegistryObjectManager() override;
void Add(const SmartPointer& registryObject, bool hold);
SmartPointer GetObject(int id, short type) const override;
- // The current impementation of this method assumes that we don't cache dynamic
+ // The current implementation of this method assumes that we don't cache dynamic
// extension. In this case all extensions not yet loaded (i.e. not in the memory cache)
// are "not dynamic" and we actually check memory objects to see if they are dynamic.
//
// If we decide to allow caching of dynamic objects, the implementation
// of this method would have to retrieved the object from disk and check
// its "dynamic" status. The problem is that id alone is not enough to get the object
// from the disk; object type is needed as well.
bool ShouldPersist(int id) const;
QList > GetObjects(const QList& values, short type) const override;
SmartPointer GetHandle(int id, short type) const override;
QList > GetHandles(const QList& ids, short type) const override;
bool IsDirty() const;
void MarkDirty();
void Close() override;
ExtensionRegistry* GetRegistry() const;
QList > GetExtensionsFromContributor(const QString& contributorId) const;
QList > GetExtensionPointsFromContributor(const QString& contributorId) const;
QList > GetExtensionPointsFromNamespace(const QString& namespaceName) const;
// This method filters out extensions with no extension point
QList > GetExtensionsFromNamespace(const QString& namespaceName) const;
SmartPointer GetContributor(const QString& id) const;
protected:
friend class Extension;
friend class ExtensionPoint;
friend class ExtensionRegistry;
friend class ExtensionsParser;
friend class RegistryContribution;
friend class RegistryObject;
mutable QMutex mutex;
static const int CACHE_INITIAL_SIZE; // = 512;
static int UNKNOWN;
typedef QHash > OrphansMapType;
typedef QHash > ContributorsMapType;
/**
* Initialize the object manager. Return true if the initialization succeeded, false otherwise
*/
bool Init(long timeStamp);
void AddContribution(const SmartPointer& contribution);
QList GetExtensionPointsFrom(const QString& id) const;
QList GetExtensionPointsFrom_unlocked(const QString& id) const;
bool HasContribution(const QString& id) const;
void Remove(int id, bool release);
void Remove_unlocked(int id, bool release);
QList > GetObjects_unlocked(const QList& values, short type) const;
SmartPointer GetExtensionPointObject(const QString& xptUniqueId) const;
SmartPointer GetExtensionPointObject_unlocked(const QString& xptUniqueId) const;
QList > GetExtensionPointsHandles() const;
SmartPointer GetExtensionPointHandle(const QString& xptUniqueId);
QList GetExtensionsFrom(const QString& contributorId) const;
QList GetExtensionsFrom_unlocked(const QString& contributorId) const;
bool AddExtensionPoint(const SmartPointer& currentExtPoint, bool hold);
void RemoveExtensionPoint(const QString& extensionPointId);
void RemoveContribution(const QString &contributorId);
void AddOrphans(const QString& extensionPoint, const QList& extensions);
void AddOrphan(const QString& extensionPoint, int extension);
QList RemoveOrphans(const QString& extensionPoint);
void RemoveOrphan(const QString& extensionPoint, int extension);
//This method is only used by the writer to reach in
QHash > GetOrphanExtensions() const;
// This method is only used by the writer to reach in
int GetNextId() const;
// This method is only used by the writer to reach in
HashtableOfStringAndInt GetExtensionPoints() const;
// This method is only used by the writer to reach in
QList GetContributions() const;
// This method is used internally and by the writer to reach in. Notice that it doesn't
// return contributors marked as removed.
ContributorsMapType& GetContributors() const;
// only adds a contributor if it is not already present in the table
void AddContributor(const SmartPointer& newContributor);
void RemoveContributor(const QString& id);
KeyedHashSet& GetNamespacesIndex() const;
/**
* Collect all the objects that are removed by this operation and store
* them in a IObjectManager so that they can be accessed from the appropriate
* deltas but not from the registry.
*/
QHash > GetAssociatedObjects(const QString& contributionId) const;
/**
* Adds elements to be removed along with the registry object.
*/
void AddAssociatedObjects(QHash >& map,
const SmartPointer