/* * Copyright (c) 2006 Stiftung Deutsches Elektronen-Synchroton, * Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY. * * THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS. * WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE * IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR * CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. * NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. * DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, * OR MODIFICATIONS. * THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION, * USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS * PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY * AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM */ package org.csstudio.sds.internal.rules; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import org.csstudio.sds.ErrorMessagesTracker; import org.csstudio.sds.SdsPlugin; import org.csstudio.sds.internal.model.logic.ScriptedRule; import org.csstudio.sds.internal.preferences.PreferenceConstants; import org.csstudio.sds.model.IRule; import org.csstudio.sds.model.PropertyTypesEnum; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.mozilla.javascript.RhinoException; /** * This class provides access to all available rules. * * @author Alexander Will * @version $Revision: 1.2 $ * */ public final class RuleService extends ErrorMessagesTracker { /** * The workspace project that holds all the rules. */ public static final String SCRIPT_PROJECT_NAME = "SDS Script Rules"; //$NON-NLS-1$ /** * The file extension of SDS scripts. */ public static final String SCRIPT_FILE_EXTENSION = "css-sdss"; //$NON-NLS-1$ /** * The shared instance of this class. */ private static RuleService _instance = null; /** * All registered Java rules that are registered via an extension point. */ private Map<String, RuleDescriptor> _javaRuleDescriptors = null; /** * All registered script rules. */ private Map<String, RuleDescriptor> _scriptRuleDescriptors = null; private String defaultAdditionalScriptFolder = "CSS/SDS/SDS_Script_Rules"; /** * Private constructor due to the singleton pattern. */ private RuleService() { _javaRuleDescriptors = Collections .synchronizedMap(new HashMap<String, RuleDescriptor>()); _scriptRuleDescriptors = Collections .synchronizedMap(new HashMap<String, RuleDescriptor>()); lookupExtensions(); lookupScripts(); } /** * Return the shared instance of this class. * * @return The shared instance of this class. */ public static RuleService getInstance() { if (_instance == null) { _instance = new RuleService(); } return _instance; } /** * Return the rule descriptor for the given rulee ID. * * @param ruleId * A rule ID. * @return The rule descriptor for the given type ID. */ public RuleDescriptor getRuleDescriptor(final String ruleId) { if (_javaRuleDescriptors.containsKey(ruleId)) { return _javaRuleDescriptors.get(ruleId); } return _scriptRuleDescriptors.get(ruleId); } /** * Perform a lookup for plugins that provide extensions for the * <code>rules</code> extension point. */ private void lookupExtensions() { IExtensionRegistry extReg = Platform.getExtensionRegistry(); String id = SdsPlugin.EXTPOINT_RULES; IConfigurationElement[] confElements = extReg .getConfigurationElementsFor(id); for (IConfigurationElement element : confElements) { IRule type = null; String ruleId = element.getAttribute("ruleId"); //$NON-NLS-1$ String description = element.getAttribute("name"); //$NON-NLS-1$ String[] parameterDescriptions = null; IConfigurationElement[] parameterElements = element .getChildren("parameterDescription"); //$NON-NLS-1$ if (parameterElements != null) { parameterDescriptions = new String[parameterElements.length]; int i = 0; for (IConfigurationElement parameterElement : parameterElements) { String parameterDescription = parameterElement .getAttribute("name"); //$NON-NLS-1$ parameterDescriptions[i] = parameterDescription; i++; } } try { type = (IRule) element.createExecutableExtension("class"); //$NON-NLS-1$ } catch (CoreException e) { trackException(e); } PropertyTypesEnum[] compatiblePropertyIds = getPropertyTypes(element .getAttribute("compatibleProperties")); if (type != null && ruleId != null) { RuleDescriptor descriptor = new RuleDescriptor(ruleId, description, parameterDescriptions, compatiblePropertyIds, type, false); _javaRuleDescriptors.put(ruleId, descriptor); } } } private PropertyTypesEnum[] getPropertyTypes(String attribute) { List<PropertyTypesEnum> result = new LinkedList<PropertyTypesEnum>(); if (attribute != null) { if (attribute.contains("*")) { return PropertyTypesEnum.values(); } String[] ids = attribute.split(","); for (String id : ids) { try { result.add(PropertyTypesEnum.createFromPortable(id.trim())); } catch (Exception e) { e.printStackTrace(); } } } return result.toArray(new PropertyTypesEnum[result.size()]); } /** * Register the scripted rules. */ private void lookupScripts() { IProject scriptProject = ResourcesPlugin.getWorkspace().getRoot() .getProject(SCRIPT_PROJECT_NAME); try { IResource[] resources = scriptProject.members(); findFiles(resources); } catch (Exception ex) { trackException(ex); } this.lookAtAdditionalLocations(); } private void lookAtAdditionalLocations() { IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); for (String folder : determineAdditionalFolders()) { IPath path = new Path(folder); IFolder folder2 = root.getFolder(path); if (folder2.exists()) { try { this.findFiles(folder2.members()); } catch (CoreException e) { // nothing to do trackException(e); } } } } private List<String> determineAdditionalFolders() { String stringList = Platform.getPreferencesService().getString( SdsPlugin.getDefault().getBundle().getSymbolicName(), PreferenceConstants.PROP_RULE_FOLDERS, "", null); List<String> result = parseString(stringList); result.add(defaultAdditionalScriptFolder); return result; } /* * (non-Javadoc) Method declared on ListEditor. */ private List<String> parseString(String stringList) { StringTokenizer st = new StringTokenizer(stringList, File.pathSeparator + "\n\r");//$NON-NLS-1$ List<String> result = new ArrayList<String>(); while (st.hasMoreElements()) { result.add((String) st.nextElement()); } return result; } private void findFiles(IResource[] resources) throws CoreException { for (IResource resource : resources) { if (resource instanceof IFile && SCRIPT_FILE_EXTENSION.equalsIgnoreCase(resource .getFileExtension())) { IFile scriptFile = (IFile) resource; updateScriptedRule(scriptFile.getName(), scriptFile); } else if (resource instanceof IFolder) { findFiles(((IFolder) resource).members()); } } } /** * Update the definition of a scripted rule. * * @param ruleId * The ID of the rule. * @param scriptFile * The file resource that contains a script rule or * <code>null</code> to remove the rule definition. */ public void updateScriptedRule(final String ruleId, final IFile scriptFile) { try { if (_scriptRuleDescriptors.containsKey(ruleId)) { _scriptRuleDescriptors.remove(ruleId); } if (scriptFile != null) { ScriptedRule type = new ScriptedRule(ruleId, scriptFile .getContents()); RuleDescriptor typeDescriptor = new RuleDescriptor(ruleId, type .getDescription(), type.getParameterDescriptions(), type.getCompatiblePropertyTypes(), type, true); _scriptRuleDescriptors.put(ruleId, typeDescriptor); } } catch (Exception ex) { trackException(ex); } } /** * Track the given exception. * * @param e * The exception to track. */ private void trackException(final Exception e) { Throwable cause = e.getCause(); String errorMessage = e.getMessage(); if (cause != null) { if (cause instanceof RhinoException) { RhinoException re = (RhinoException) cause; errorMessage += "\n The cause was [" + re.getMessage() + "]."; //$NON-NLS-1$ //$NON-NLS-2$ } } trackErrorMessage(errorMessage); } /** * @return A list which contains all rule descriptors. */ public List<RuleDescriptor> getRegisteredRuleDescriptors() { lookupScripts(); ArrayList<RuleDescriptor> result = new ArrayList<RuleDescriptor>(); result.addAll(_javaRuleDescriptors.values()); result.addAll(_scriptRuleDescriptors.values()); return result; } }