All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openbp.cockpit.Cockpit Maven / Gradle / Ivy

The newest version!
/*
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
package org.openbp.cockpit;

import javax.swing.ImageIcon;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;

import org.openbp.cockpit.generator.GeneratorMgr;
import org.openbp.cockpit.generator.GeneratorPlugin;
import org.openbp.cockpit.itemeditor.ItemOpenDispatcherPlugin;
import org.openbp.cockpit.itemeditor.NodeItemEditor;
import org.openbp.cockpit.itemeditor.StandardItemEditor;
import org.openbp.cockpit.modeler.ModelerOptionPlugin;
import org.openbp.cockpit.modeler.ModelerPage;
import org.openbp.cockpit.modeler.figures.process.ProcessElementFigureRegistry;
import org.openbp.cockpit.modeler.skins.SkinMgr;
import org.openbp.cockpit.modeler.skins.SkinPlugin;
import org.openbp.cockpit.plugins.association.AssociationPlugin;
import org.openbp.cockpit.plugins.association.ExternalAssociationPlugin;
import org.openbp.cockpit.plugins.commandline.CommandLinePlugin;
import org.openbp.common.ExceptionUtil;
import org.openbp.common.application.Application;
import org.openbp.common.generic.propertybrowser.ObjectDescriptorMgr;
import org.openbp.common.io.xml.XMLDriverException;
import org.openbp.common.rc.ResourceCollectionMgr;
import org.openbp.common.rc.ResourceCollectionUtil;
import org.openbp.common.resource.FileResourceProvider;
import org.openbp.common.resource.ResourceMgr;
import org.openbp.common.setting.SettingUtil;
import org.openbp.common.string.StringUtil;
import org.openbp.core.CoreModule;
import org.openbp.core.MimeTypes;
import org.openbp.core.OpenBPException;
import org.openbp.core.model.Association;
import org.openbp.core.model.Model;
import org.openbp.core.model.ModelObjectSymbolNames;
import org.openbp.core.model.item.ItemTypes;
import org.openbp.core.model.item.activity.JavaActivityItem;
import org.openbp.core.model.item.process.ProcessItem;
import org.openbp.core.model.item.visual.VisualItem;
import org.openbp.core.remote.ClientLoginInfo;
import org.openbp.guiclient.GUIClientModule;
import org.openbp.guiclient.model.ModelConnector;
import org.openbp.guiclient.model.item.ItemEditorRegistry;
import org.openbp.guiclient.plugins.displayobject.DisplayObjectPlugin;
import org.openbp.guiclient.plugins.server.ServerConnectionPlugin;
import org.openbp.guiclient.remote.ServerConnection;
import org.openbp.jaspira.action.JaspiraAction;
import org.openbp.jaspira.action.JaspiraActionEvent;
import org.openbp.jaspira.event.JaspiraEventHandlerCode;
import org.openbp.jaspira.event.JaspiraEventMgr;
import org.openbp.jaspira.gui.plugin.ApplicationBase;
import org.openbp.jaspira.gui.plugin.JaspiraPage;
import org.openbp.jaspira.plugin.ApplicationUtil;
import org.openbp.jaspira.plugin.ConfigMgr;
import org.openbp.jaspira.plugin.EventModule;
import org.openbp.jaspira.plugin.PluginMgr;
import org.openbp.jaspira.plugins.errordialog.ErrorDialogPlugin;
import org.openbp.jaspira.propertybrowser.NodeStructureMgr;
import org.openbp.swing.SwingUtil;
import org.openbp.swing.components.JMsgBox;
import org.springframework.core.io.ResourceLoader;

/**
 * Main class of the OpenBP cockpit.
 *
 * @author Jens Ferchland
 */
public class Cockpit extends ApplicationBase
{
	/** The splash screen of the application. */
	private static SplashScreen splashScreen;

	/** Debug flag: Disable all continously running timers (useful for profiling and memory leak detection) */
	public static boolean disableTimersForDebug = false;

	//////////////////////////////////////////////////
	// @@ Plugin overrides
	//////////////////////////////////////////////////

	/**
	 * Constructor.
	 * Initializes the application.
	 * This will register the ApplicationBase as a regular plugin.
	 * This in turn will invoke the install method, which may perform further plugin loading etc.
	 */
	public Cockpit()
	{
	}

	public String getResourceCollectionContainerName()
	{
		return "plugin.cockpit";
	}

	/**
	 * Template method that is called before the actual installation of the application base plugin is performed.
	 */
	protected void preInstallApplication()
	{
		if (disableTimersForDebug)
		{
			ServerConnection.disableTimersForDebug = true;
		}

		// Initialize core and client and set up the server connection
		super.preInstallApplication();

		String resourceDir = SettingUtil.getStringSetting("openbp.cockpit.resource.dir");
		if (resourceDir != null)
		{
			ResourceLoader loader = ResourceMgr.getDefaultInstance().getResourceLoader();
			FileResourceProvider rp = new FileResourceProvider(ResourceMgr.ROOTDIR_RESOURCE_PROVIDER_PRIO + 1, loader, resourceDir);
			ResourceMgr.getDefaultInstance().getResourceResolver().addProvider(rp);
		}

		// Load base plugins
		PluginMgr.getInstance().createInstance(ServerConnectionPlugin.class, this);

		registerItemEditors();
		registerFigureClasses();
	}

	/**
	 * Template method that is called after the actual installation of the application base plugin is performed.
	 */
	protected void postInstallApplication()
	{
		super.postInstallApplication();

		PluginMgr pm = PluginMgr.getInstance();

		// Initialize the client environment
		GUIClientModule.getInstance().initialize();

		// This will load the model data.
		ModelConnector.getInstance().initialize(GUIClientModule.getInstance());

		// Set the custom descriptor directory and custom descriptor set name specified by the user
		initCustomDescriptors();

		// Add global plugins
		// This will automatically create the display object plugin
		DisplayObjectPlugin.getInstance();

		// Load all skin data and initialize the icon model accordingly
		SkinMgr.getInstance().load();

		// Add these plugins first, they will create menu items for the global menu
		pm.createInstance(ErrorDialogPlugin.class, this);

		// Try to connect to the server
		// By default, use an anonymous login
		ServerConnection connection = ServerConnection.getInstance();
		connection.setLoginInfo(new ClientLoginInfo("Anonymous", null));
		try
		{
			connection.connect(true);
		}
		catch (OpenBPException e)
		{
			// Show dialog box if the user has not chose to skip it before
			if (! SettingUtil.getBooleanSetting("openbp.cockpit.connectionwarning.hide", false))
			{
				// Hide splash screen.
				if (splashScreen != null)
				{
					splashScreen.setVisible(false);
				}

				int response = JMsgBox.show(null, getPluginResourceCollection().getRequiredString(
					"connectionerror.title"), ResourceCollectionUtil.formatMsg(getPluginResourceCollection(),
					"connectionerror.description", new Object[]
					{
						connection.getConnectionInfo().getRmiServerHost(),
						new Integer(connection.getConnectionInfo().getRmiServerPort()), e.getMessage()
					}), JMsgBox.ICON_INFO | JMsgBox.TYPE_OK | JMsgBox.DEFAULT_OK | JMsgBox.TYPE_DO_NOT_SHOW_AGAIN);

				if ((response & JMsgBox.TYPE_DO_NOT_SHOW_AGAIN) != 0)
				{
					// Skip this dialog the next time
					SettingUtil.setBooleanSetting("openbp.cockpit.connectionwarning.hide", true);
					SettingUtil.saveSettings(null);
				}
			}
		}

		// After adding the first page, we have a component we need for the glass pane access
		// for the wait cursor, so turn it on now
		ApplicationUtil.waitCursorOn();

		try
		{
			// Add the standard pages
			addPage((JaspiraPage) pm.createInstance(ModelerPage.class, this));

			pm.createInstance(GeneratorPlugin.class, this);

			// pm.createInstance (DataTypeSearchPlugin.class, this);
			// pm.createInstance(EclipseEditorPlugin.class, this);

			pm.createInstance(ModelerOptionPlugin.class, this);
			pm.createInstance(SkinPlugin.class, this);

			pm.createInstance(ItemOpenDispatcherPlugin.class, this);
			pm.createInstance(CommandLinePlugin.class, this);
			pm.createInstance(ExternalAssociationPlugin.class, this);
			pm.createInstance(AssociationPlugin.class, this);

			// Load global custom plugins
			PluginMgr.getInstance().loadCustomPlugins("openbp.cockpit.plugins.global");

			// Load custom plugins from the 'plugin' directory.
			PluginMgr.getInstance().loadPluginsFromResource();
		}
		finally
		{
			// Reset the wait cursor
			ApplicationUtil.waitCursorOff();
		}

		// Disable the save button initially
		JaspiraAction action = getAction("standard.file.save");
		if (action != null)
		{
			action.setEnabled(false);
		}

		// Make the tool tips stay long enough to be read
		ToolTipManager.sharedInstance().setDismissDelay(10000);

		// Write out that startup is complete.
		System.out.println("OpenBP cockpit startup complete");
	}

	/**
	 * @see org.openbp.jaspira.gui.plugin.ApplicationBase#getAboutBoxClass()
	 */
	protected Class getAboutBoxClass()
	{
		return CockpitAboutBox.class;
	}

	/**
	 * Registers the default item editors.
	 */
	private void registerItemEditors()
	{
		ItemEditorRegistry registry = ItemEditorRegistry.getInstance();

		StandardItemEditor standardItemEditor = new StandardItemEditor();
		NodeItemEditor nodeItemEditor = new NodeItemEditor();

		registry.registerItemEditor(ItemTypes.ACTIVITY, nodeItemEditor);
		registry.registerItemEditor(ModelObjectSymbolNames.PLACEHOLDER_NODE, nodeItemEditor);
		registry.registerItemEditor(ItemTypes.PROCESS, nodeItemEditor);
		registry.registerItemEditor(ItemTypes.TYPE, standardItemEditor);
		registry.registerItemEditor(ItemTypes.MODEL, standardItemEditor);
		registry.registerItemEditor(ItemTypes.VISUAL, nodeItemEditor);
	}

	/**
	 * Registers the default process element figure classes.
	 */
	private void registerFigureClasses()
	{
		ProcessElementFigureRegistry registry = ProcessElementFigureRegistry.getInstance();

		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.DecisionNodeFigure.class,
			org.openbp.core.model.item.process.DecisionNode.class);
		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.FinalNodeFigure.class,
			org.openbp.core.model.item.process.FinalNode.class);
		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.FlowConnection.class,
			org.openbp.core.model.item.process.ControlLink.class);
		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.ForkNodeFigure.class,
			org.openbp.core.model.item.process.ForkNode.class);
		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.InitialNodeFigure.class,
			org.openbp.core.model.item.process.InitialNode.class);
		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.JoinNodeFigure.class,
			org.openbp.core.model.item.process.JoinNode.class);
		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.MergeNodeFigure.class,
			org.openbp.core.model.item.process.MergeNode.class);
		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.ParamConnection.class,
			org.openbp.core.model.item.process.DataLink.class);
		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.PlaceholderNodeFigure.class,
			org.openbp.core.model.item.process.PlaceholderNode.class);
		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.TextElementFigure.class,
			org.openbp.core.model.item.process.TextElement.class);
		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.WaitStateNodeFigure.class,
			org.openbp.core.model.item.process.WaitStateNode.class);
		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.WorkflowEndNodeFigure.class,
			org.openbp.core.model.item.process.WorkflowEndNode.class);
		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.WorkflowNodeFigure.class,
			org.openbp.core.model.item.process.WorkflowNode.class);

		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.MultiSocketNodeFigure.class,
			org.openbp.core.model.item.process.ActivityNode.class);
		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.MultiSocketNodeFigure.class,
			org.openbp.core.model.item.process.SubprocessNode.class);
		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.MultiSocketNodeFigure.class,
			org.openbp.core.model.item.process.VisualNode.class);
		registry.registerFigure(org.openbp.cockpit.modeler.figures.process.MultiSocketNodeFigure.class,
			org.openbp.core.model.item.process.WebServiceNode.class);
	}

	/**
	 * Initializes custom descriptors.
	 * Sets the custom descriptor directory and loads the current custom descriptor set, if any.
	 */
	private void initCustomDescriptors()
	{
		ObjectDescriptorMgr.getInstance().setCustomDescriptorResourcePath(CockpitConstants.CUSTOM_OBJECT_DESCRIPTOR_SETS);

		loadCustomDescriptors();
	}

	/**
	 * Resets custom descriptors.
	 * Reloads the current custom descriptor set, if any.
	 */
	private void loadCustomDescriptors()
	{
		// Must clear the property browser node structure manager's cache for the
		// custom object descriptors to take effect.
		NodeStructureMgr.getInstance().clearCache();

		String customDescriptorSetName = SettingUtil.getStringSetting("openbp.cockpit.codset");
		try
		{
			ObjectDescriptorMgr.getInstance().loadCustomDescriptorSet(customDescriptorSetName);

			// Refresh all property browsers, so the new object descriptors apply
			fireEvent("plugin.propertybrowser.refresh");
		}
		catch (XMLDriverException e)
		{
			// Already logged, ignore here
			JMsgBox.show(null, e.getMessage(), JMsgBox.ICON_ERROR);
		}
	}

	/**
	 * Prints a Cockpit restart hint.
	 */
	public void displayRestartHint()
	{
		SwingUtilities.invokeLater(new Runnable()
		{
			public void run()
			{
				// Issue a warning message that the Cockpit needs to be restarted
				String msg = getPluginResourceCollection().getRequiredString("warning.restartoption");
				JMsgBox.show(null, msg, JMsgBox.ICON_WARNING);
			}
		});
	}

	//////////////////////////////////////////////////
	// @@ Helpers
	//////////////////////////////////////////////////

	/** Contains some classes that are likely to displayed by the model page's property browser */
	private static final Class[] objectClassPreloads =
	{
		Model.class, JavaActivityItem.class, ProcessItem.class, VisualItem.class,
	};

	/**
	 * Preloads certain configuration data.
	 */
	// TODO Feature 5 Private method unused; made protected to prevent compiler warning 
	protected void performPreload()
	{
		// Load the list of generators
		showStatusText(getPluginResourceCollection().getRequiredString("progress.loadingwizards"));
		GeneratorMgr.getInstance();

		showStatusText(getPluginResourceCollection().getRequiredString("progress.loadingobjectdescriptors"));
		NodeStructureMgr nsm = NodeStructureMgr.getInstance();
		for (int i = 0; i < objectClassPreloads.length; ++i)
		{
			Class cls = objectClassPreloads[i];
			nsm.loadNodeStructureFor(cls);
		}
	}

	//////////////////////////////////////////////////
	// @@ Help event module
	//////////////////////////////////////////////////

	/**
	 * This event module containts event handlers for the implementation of
	 * functions of the help menu.
	 */
	public class HelpEvents extends EventModule
	{
		public String getName()
		{
			return "cockpit";
		}

		/**
		 * Event handler: Display the help overview as PDF document.
		 *
		 * @event cockpit.help.manual
		 * @param je Event
		 * @return The event status code
		 */
		public JaspiraEventHandlerCode cockpit_help_manual(JaspiraActionEvent je)
		{
			openGuide(CockpitConstants.DOC_MANUAL);

			return EVENT_CONSUMED;
		}

		/**
		 * Event handler: Display the Java API documentation as HTML.
		 *
		 * @event cockpit.help.javaapi
		 * @param je Event
		 * @return The event status code
		 */
		public JaspiraEventHandlerCode cockpit_help_javaapi(JaspiraActionEvent je)
		{
			openGuide(CockpitConstants.DOC_JAVA_API);

			return EVENT_CONSUMED;
		}

		/**
		 * Opens a documentation file in the 'doc' directory of the OpenBP installation.
		 *
		 * @param name Name of the file to open
		 */
		private void openGuide(String name)
		{
			String path = Application.getRootDir() + StringUtil.FOLDER_SEP + "doc" + StringUtil.FOLDER_SEP + name;

			boolean pdf = path.endsWith(".pdf");

			Association as = new Association();
			if (pdf)
			{
				as.setAssociationTypes(new String[]
				{
					MimeTypes.APPLICATION_PDF
				});
			}
			else
			{
				as.setAssociationTypes(new String[]
				{
					MimeTypes.HTML_FILE, MimeTypes.URL
				});
			}
			as.setAssociationPriority(Association.PRIMARY);
			as.setAssociatedObject(path);
			boolean consumed = JaspiraEventMgr.fireGlobalEvent("plugin.association.tryopen", as);

			if (! consumed)
			{
				String msg = getPluginResourceCollection().getRequiredString(
					pdf ? "guide.noassociation.pdf" : "guide.noassociation.html");
				JMsgBox.show(null, msg, JMsgBox.ICON_WARNING);
			}
		}
	}

	//////////////////////////////////////////////////
	// @@ Main method
	//////////////////////////////////////////////////

	/**
	 * Main method.
	 */
	public static void main(String[] args)
	{
		try
		{
			CoreModule.determineRootDir();
			Application.setArguments(args);

			Application.initialize();
			Application.registerPropertyResource("OpenBP-Cockpit.properties", 80, false);
			Application.registerPropertyResource("OpenBP-User.properties", 90, true);
			ConfigMgr.getInstance().setConfigResourceName("OpenBP-Cockpit-Config.properties");

			addResourceCollectionTextReplacement("openbp.application.name");
			addResourceCollectionTextReplacement("openbp.application.title");
			addResourceCollectionTextReplacement("openbp.cockpit.title");

			String applicationName = SettingUtil.getMandatoryStringSetting("openbp.application.name");
			String resourceName = ResourceCollectionMgr.RC_FOLDER + "/images/application/" + applicationName + "Splash.png";

			if (! SettingUtil.getBooleanSetting("openbp.application.nosplash", false))
			{
				try
				{
					ResourceMgr resourceMgr = ResourceMgr.getDefaultInstance();
					byte[] imageData = resourceMgr.loadByteResource(resourceName);

					ImageIcon image = new ImageIcon(imageData);

					splashScreen = new SplashScreen(image);
					splashScreen.setLocationRelativeTo(null);
					SwingUtil.show(splashScreen);

					// Turn on the the wait cursor using the spash screen as frame
					SwingUtil.waitCursorOn(splashScreen);
				}
				catch (Exception e)
				{
					// Ignore any errors
				}
			}

			// Instantiate the application class and register it as a plugin
			// This will cause the ApplicationBase.initialize method to be called,
			// which in turn calls {@link #preInstallApplication} and {@link #postInstallApplication}.
			new Cockpit();
		}
		catch (Exception e)
		{
			if (splashScreen != null)
			{
				splashScreen.dispose();
			}
			ExceptionUtil.printTrace(e);
			System.exit(1);
		}
		finally
		{
			if (splashScreen != null)
			{
				splashScreen.dispose();
			}
		}
	}

	/**
	 * Initializes global resource text replacements.
	 *
	 * @param key Resource key
	 */
	private static void addResourceCollectionTextReplacement(String key)
	{
		String value = SettingUtil.getStringSetting(key, key);
		ResourceCollectionMgr.getDefaultInstance().addResourceVariable("$(" + key + ")", value);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy