| /******************************************************************************* |
| * Copyright (c) 2007, 2008 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * yyyymmdd bug Email and other contact information |
| * -------- -------- ----------------------------------------------------------- |
| * 20071024 196997 pmoogk@ca.ibm.com - Peter Moogk |
| * 20071113 209701 pmoogk@ca.ibm.com - Peter Moogk |
| * 20080111 214907 pmoogk@ca.ibm.com - Peter Moogk |
| * 20080214 218996 pmoogk@ca.ibm.com - Peter Moogk, Concurrent exception fix |
| * 20080325 222095 pmoogk@ca.ibm.com - Peter Moogk |
| * 20080625 238482 pmoogk@ca.ibm.com - Peter Moogk, Adding thread safety to the service platform api. |
| *******************************************************************************/ |
| package org.eclipse.wst.ws.service.internal.policy; |
| |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.Vector; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import org.eclipse.core.expressions.EvaluationContext; |
| import org.eclipse.core.expressions.EvaluationResult; |
| import org.eclipse.core.expressions.Expression; |
| import org.eclipse.core.expressions.IEvaluationContext; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.ProjectScope; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.preferences.IEclipsePreferences; |
| import org.eclipse.wst.ws.service.policy.IFilter; |
| import org.eclipse.wst.ws.service.policy.IServicePolicy; |
| import org.eclipse.wst.ws.service.policy.IStateEnumerationItem; |
| import org.eclipse.wst.ws.service.policy.ServicePolicyActivator; |
| import org.eclipse.wst.ws.service.policy.ServicePolicyPlatform; |
| import org.eclipse.wst.ws.service.policy.listeners.IPolicyChildChangeListener; |
| import org.eclipse.wst.ws.service.policy.listeners.IPolicyPlatformLoadListener; |
| import org.eclipse.wst.ws.service.policy.listeners.IPolicyPlatformProjectLoadListener; |
| import org.osgi.service.prefs.BackingStoreException; |
| |
| |
| public class ServicePolicyPlatformImpl |
| { |
| private List<IPolicyPlatformLoadListener> loadListeners; |
| private Map<String, ServicePolicyImpl> committedPolicyMap; |
| private Map<String, ServicePolicyImpl> policyMap; |
| private Map<String, List<IStateEnumerationItem>> enumList; |
| private Map<String, StateEnumerationItemImpl> enumItemList; |
| private Map<IProject, ProjectEntry> enabledProjectMap; |
| private List<Expression> enabledList; |
| private List<IPolicyChildChangeListener> childChangeListeners; |
| private List<IPolicyChildChangeListener> childChangeListenersOnCommit; |
| private List<IServicePolicy> commitChildChangePolicy; |
| private List<Boolean> commitChildChangeAdded; |
| private List<IServicePolicy> queuedChildChangePolicy; |
| private List<Boolean> queuedChildChangeAdded; |
| private List<IPolicyPlatformProjectLoadListener> projectPlatformListeners; |
| private ServicePolicyPlatform apiPlatform; |
| |
| public ServicePolicyPlatformImpl( ServicePolicyPlatform platform ) |
| { |
| apiPlatform = platform; |
| } |
| |
| public void load() |
| { |
| ServicePolicyRegistry registry = new ServicePolicyRegistry( this ); |
| List<String> localIds = LocalUtils.getLocalPolicyIds(); |
| |
| loadListeners = new Vector<IPolicyPlatformLoadListener>(); |
| policyMap = new HashMap<String, ServicePolicyImpl>(); |
| enumList = new HashMap<String, List<IStateEnumerationItem>>(); |
| enumItemList = new HashMap<String, StateEnumerationItemImpl>(); |
| enabledProjectMap = new HashMap<IProject, ProjectEntry>(); |
| enabledList = new Vector<Expression>(); |
| |
| childChangeListeners = new Vector<IPolicyChildChangeListener>(); |
| childChangeListenersOnCommit = new Vector<IPolicyChildChangeListener>(); |
| commitChildChangePolicy = new Vector<IServicePolicy>(); |
| commitChildChangeAdded = new Vector<Boolean>(); |
| projectPlatformListeners = new Vector<IPolicyPlatformProjectLoadListener>(); |
| |
| registry.load( loadListeners, policyMap, enumList, enumItemList ); |
| |
| // This first loop through the ids will only create service policy objects |
| // without populating them with there values. |
| for( String localPolicyId : localIds ) |
| { |
| ServicePolicyImpl localPolicy = new ServicePolicyImpl( false, localPolicyId, this ); |
| |
| policyMap.put( localPolicyId, localPolicy ); |
| } |
| |
| // This second loop will populate the service policy values and |
| // crossreference parent and child service policies. |
| for( String localPolicyId : localIds ) |
| { |
| LocalUtils.loadLocalPolicy( localPolicyId, this ); |
| } |
| } |
| |
| public void callLoadListeners() |
| { |
| for( IPolicyPlatformLoadListener loadListener : loadListeners ) |
| { |
| try |
| { |
| loadListener.load(); |
| } |
| catch( Exception exc ) |
| { |
| ServicePolicyActivator.logError( "Error in load listener:" + loadListener.getClass().getName(), exc ); //$NON-NLS-1$ |
| } |
| } |
| |
| commitChanges( false ); |
| |
| // Commit any project level changes that have been made by load listeners. |
| for( IProject project : enabledProjectMap.keySet() ) |
| { |
| commitChanges( project ); |
| } |
| } |
| |
| public ServicePolicyPlatform getApiPlatform() |
| { |
| return apiPlatform; |
| } |
| |
| public void addEnabledExpression( Expression expression ) |
| { |
| if( expression != null ) |
| { |
| enabledList.add( expression ); |
| } |
| } |
| |
| public boolean isEnabled( Object object ) |
| { |
| boolean result = false; |
| IEvaluationContext context = new EvaluationContext( null, object ); |
| context.addVariable( "selection", object ); //$NON-NLS-1$ |
| context.setAllowPluginActivation( true ); |
| |
| for( Expression enabledItem : enabledList ) |
| { |
| try |
| { |
| EvaluationResult expResult = enabledItem.evaluate( context ); |
| |
| // If any expression returns TRUE or NOT_LOADED we will return true as |
| // the result. |
| if( expResult != EvaluationResult.FALSE ) |
| { |
| result = true; |
| break; |
| } |
| } |
| catch( CoreException exc ) |
| { |
| // Ignore the expression if an exception occurs. |
| ServicePolicyActivator.logError( "Error evaluating enablement expression.", exc ); //$NON-NLS-1$ |
| } |
| } |
| |
| return result; |
| } |
| |
| public void commitChanges( boolean saveLocals ) |
| { |
| List<String> localIds = new Vector<String>(); |
| |
| if( saveLocals ) LocalUtils.removeAllPreferencePolicies( null, null ); |
| |
| // Fire child change events for commit listeners |
| for( IPolicyChildChangeListener listener : childChangeListenersOnCommit ) |
| { |
| listener.childChange( commitChildChangePolicy, commitChildChangeAdded ); |
| } |
| |
| removeDeletedPreferenceData(); |
| |
| commitChildChangePolicy = new Vector<IServicePolicy>(); |
| commitChildChangeAdded = new Vector<Boolean>(); |
| |
| for( ServicePolicyImpl policy : policyMap.values() ) |
| { |
| policy.commitChanges(); |
| |
| if( saveLocals && !policy.isPredefined() ) |
| { |
| LocalUtils.saveLocalPolicy( policy ); |
| localIds.add( policy.getId() ); |
| } |
| } |
| |
| if( saveLocals ) LocalUtils.saveLocalIds( localIds ); |
| |
| committedPolicyMap = new HashMap<String, ServicePolicyImpl>(); |
| committedPolicyMap.putAll( policyMap ); |
| ServicePolicyActivator.getDefault().savePluginPreferences(); |
| } |
| |
| private void removeDeletedPreferenceData() |
| { |
| for( int index = 0; index < commitChildChangePolicy.size(); index++ ) |
| { |
| IServicePolicy policy = commitChildChangePolicy.get( index ); |
| boolean added = commitChildChangeAdded.get( index ); |
| |
| if( !added ) |
| { |
| // Add policy is being deleted. We need to remove any state data |
| // for this policy at the workspace level and the project level. |
| LocalUtils.removeAllPreferencePolicies( policy.getId(), null ); |
| |
| for( IProject proj : enabledProjectMap.keySet() ) |
| { |
| if( proj.exists() && proj.isOpen() ) |
| { |
| IEclipsePreferences projPrefs = new ProjectScope( proj ).getNode( ServicePolicyActivator.PLUGIN_ID ); |
| LocalUtils.removeAllPreferencePolicies( policy.getId(), projPrefs ); |
| |
| try |
| { |
| projPrefs.flush(); |
| } |
| catch( BackingStoreException exc ) |
| { |
| ServicePolicyActivator.logError( "Error flushing project properties.", exc ); //$NON-NLS-1$ |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * This method is called internally to remove a service policy. |
| * |
| * @param policy |
| */ |
| public void removePolicy( IServicePolicy policy ) |
| { |
| policyMap.remove( policy.getId() ); |
| fireChildChangeEvent( policy, false ); |
| } |
| |
| /** |
| * This method is only called from the platform API |
| * |
| * @param policy |
| */ |
| public void removePlatformPolicy( IServicePolicy policy ) |
| { |
| if( policy.isPredefined() ) return; |
| |
| IServicePolicy parent = policy.getParentPolicy(); |
| |
| if( parent == null ) |
| { |
| // Remove any children first |
| List<IServicePolicy> children = new Vector<IServicePolicy>( policy.getChildren() ); |
| |
| for( IServicePolicy child : children ) |
| { |
| policy.removeChild( child ); |
| } |
| |
| removePolicy( (ServicePolicyImpl)policy); |
| } |
| else |
| { |
| parent.removeChild( policy ); |
| } |
| } |
| |
| public void addChildChangeListener( IPolicyChildChangeListener listener, boolean onCommit ) |
| { |
| if( onCommit ) |
| { |
| childChangeListenersOnCommit.add( listener ); |
| } |
| else |
| { |
| childChangeListeners.add( listener ); |
| } |
| } |
| |
| public void removeChildChangeListener( IPolicyChildChangeListener listener, boolean onCommit ) |
| { |
| if( onCommit ) |
| { |
| childChangeListenersOnCommit.remove( listener ); |
| } |
| else |
| { |
| childChangeListeners.remove( listener ); |
| } |
| } |
| |
| public void queueChildChangeListeners( boolean queue ) |
| { |
| if( queue && queuedChildChangeAdded == null ) |
| { |
| queuedChildChangeAdded = new Vector<Boolean>(); |
| queuedChildChangePolicy = new Vector<IServicePolicy>(); |
| } |
| else if( !queue && queuedChildChangeAdded != null ) |
| { |
| // Queuing has been turned off so we will fire all the queued events. |
| for( IPolicyChildChangeListener listener : childChangeListeners ) |
| { |
| listener.childChange( queuedChildChangePolicy, queuedChildChangeAdded ); |
| } |
| |
| queuedChildChangeAdded = null; |
| queuedChildChangePolicy = null; |
| } |
| } |
| |
| public void fireChildChangeEvent( IServicePolicy policy, boolean isAdd ) |
| { |
| if( queuedChildChangeAdded == null ) |
| { |
| List<IServicePolicy> policyList = new Vector<IServicePolicy>(1); |
| List<Boolean> addedList = new Vector<Boolean>(1); |
| |
| policyList.add( policy ); |
| addedList.add( isAdd ); |
| |
| for( IPolicyChildChangeListener listener : childChangeListeners ) |
| { |
| listener.childChange( policyList, addedList ); |
| } |
| } |
| else |
| { |
| queuedChildChangeAdded.add( isAdd ); |
| queuedChildChangePolicy.add( policy ); |
| } |
| |
| commitChildChangeAdded.add( isAdd ); |
| commitChildChangePolicy.add( policy ); |
| } |
| |
| public void commitChanges( IProject project ) |
| { |
| for( ServicePolicyImpl policy : policyMap.values() ) |
| { |
| ((PolicyStateImpl)policy.getPolicyState( project )).commitChanges(); |
| } |
| |
| ProjectEntry entry = getProjectEntry( project ); |
| |
| entry.isEnabledCommitted = entry.isEnabled; |
| setProjectEnabled( project, entry.isEnabledCommitted ); |
| |
| try |
| { |
| IEclipsePreferences projectPrefs = new ProjectScope( project ).getNode( ServicePolicyActivator.PLUGIN_ID ); |
| |
| projectPrefs.flush(); |
| } |
| catch( BackingStoreException exc ) |
| { |
| ServicePolicyActivator.logError( "Error while committing project preferences.", exc ); //$NON-NLS-1$ |
| } |
| |
| } |
| |
| public void discardChanges() |
| { |
| policyMap = new HashMap<String, ServicePolicyImpl>(); |
| policyMap.putAll( committedPolicyMap ); |
| |
| commitChildChangePolicy = new Vector<IServicePolicy>(); |
| commitChildChangeAdded = new Vector<Boolean>(); |
| |
| for( ServicePolicyImpl policy : committedPolicyMap.values() ) |
| { |
| policy.discardChanges(); |
| } |
| } |
| |
| public void discardChanges( IProject project ) |
| { |
| for( ServicePolicyImpl policy : policyMap.values() ) |
| { |
| ((PolicyStateImpl)policy.getPolicyState( project )).discardChanges(); |
| } |
| |
| ProjectEntry entry = getProjectEntry( project ); |
| |
| entry.isEnabled = entry.isEnabledCommitted; |
| } |
| |
| public void restoreDefaults() |
| { |
| Vector<ServicePolicyImpl> tempPolicyValues |
| = new Vector<ServicePolicyImpl>( policyMap.values() ); |
| |
| for( ServicePolicyImpl policy : tempPolicyValues ) |
| { |
| policy.restoreDefaults(); |
| } |
| } |
| |
| public void restoreDefaults( IProject project ) |
| { |
| for( ServicePolicyImpl policy : policyMap.values() ) |
| { |
| policy.restoreDefaults( project ); |
| } |
| } |
| |
| public Set<String> getAllPolicyIds() |
| { |
| return policyMap.keySet(); |
| } |
| |
| public List<IServicePolicy> getRootServicePolicies( IFilter filter ) |
| { |
| List<IServicePolicy> rootPolicies = new Vector<IServicePolicy>(); |
| |
| for( String policyId : policyMap.keySet() ) |
| { |
| ServicePolicyImpl policy = policyMap.get( policyId ); |
| |
| if( policy.getParentPolicy() == null ) |
| { |
| if( filter == null || (filter != null && filter.accept( policy )) ) |
| { |
| rootPolicies.add( policy ); |
| } |
| } |
| } |
| |
| return rootPolicies; |
| } |
| |
| public ServicePolicyImpl createServicePolicy( IServicePolicy parent, |
| String id, |
| String enumListId, |
| String defaultEnumId ) |
| { |
| if( id == null ) id = "org.eclipse.wst.ws.service.policy.id"; //$NON-NLS-1$ |
| |
| String uniqueId = makeUniqueId( id ); |
| ServicePolicyImpl policy = new ServicePolicyImpl( false, uniqueId, this ); |
| |
| policy.setParent( (ServicePolicyImpl)parent ); |
| policy.setEnumListId( enumListId ); |
| policy.setDefaultEnumId( defaultEnumId ); |
| policyMap.put( uniqueId, policy ); |
| fireChildChangeEvent( policy, true ); |
| |
| return policy; |
| } |
| |
| public ServicePolicyImpl getServicePolicy( String id ) |
| { |
| return id == null ? null : policyMap.get( id ); |
| } |
| |
| public List<IStateEnumerationItem> getStateEnumeration( String enumId ) |
| { |
| return enumList.get( enumId ); |
| } |
| |
| public IStateEnumerationItem getStateItemEnumeration( String stateItemId ) |
| { |
| return enumItemList.get( stateItemId ); |
| } |
| |
| public boolean isProjectPreferencesEnabled( IProject project ) |
| { |
| ProjectEntry entry = getProjectEntry( project ); |
| |
| return entry.isEnabled; |
| } |
| |
| private boolean getProjectPreferenceEnabled( IProject project ) |
| { |
| String pluginId = ServicePolicyActivator.PLUGIN_ID; |
| IEclipsePreferences projectPreference = new ProjectScope( project ).getNode( pluginId ); |
| String key = pluginId + ".projectEnabled"; //$NON-NLS-1$ |
| |
| return projectPreference.getBoolean( key, false ); |
| } |
| |
| public void setProjectPreferencesEnabled( IProject project, boolean value ) |
| { |
| ProjectEntry entry = getProjectEntry( project ); |
| |
| entry.isEnabled = value; |
| } |
| |
| /** |
| * Add a project platform listener. When a particular project is referenced |
| * by in the service policy platform this listener will be called the first |
| * time the project is loaded into the system. |
| * |
| * @param listener the listener |
| */ |
| public void addProjectLoadListener( IPolicyPlatformProjectLoadListener listener ) |
| { |
| projectPlatformListeners.add( listener ); |
| } |
| |
| /** |
| * Removes a project platform listener. |
| * |
| * @param listener the listener |
| */ |
| public void removeProjectLoadListener( IPolicyPlatformProjectLoadListener listener ) |
| { |
| projectPlatformListeners.remove( listener ); |
| } |
| |
| private void setProjectEnabled( IProject project, boolean value ) |
| { |
| String pluginId = ServicePolicyActivator.PLUGIN_ID; |
| IEclipsePreferences projectPreference = new ProjectScope( project ).getNode( pluginId ); |
| String key = pluginId + ".projectEnabled"; //$NON-NLS-1$ |
| |
| projectPreference.putBoolean( key, value ); |
| } |
| |
| private ProjectEntry getProjectEntry( IProject project ) |
| { |
| ProjectEntry entry = enabledProjectMap.get( project ); |
| |
| if( entry == null ) |
| { |
| entry = new ProjectEntry(); |
| enabledProjectMap.put( project, entry ); |
| entry.isEnabledCommitted = getProjectPreferenceEnabled( project ); |
| entry.isEnabled = entry.isEnabledCommitted; |
| fireProjectLoadListener( project ); |
| } |
| |
| return entry; |
| } |
| |
| private void fireProjectLoadListener( IProject project ) |
| { |
| for( IPolicyPlatformProjectLoadListener listener : projectPlatformListeners ) |
| { |
| listener.load( project ); |
| } |
| } |
| |
| private String makeUniqueId( String id ) |
| { |
| String result = id; |
| int idCount = 1; |
| Pattern pattern = Pattern.compile( "\\d*$" ); // Match any numerical digits at the end //$NON-NLS-1$ |
| // of the string. |
| |
| while( policyMap.containsKey( result ) ) |
| { |
| Matcher matcher = pattern.matcher( result ); |
| |
| result = matcher.replaceFirst( "" ) + idCount; //$NON-NLS-1$ |
| idCount++; |
| } |
| |
| return result; |
| } |
| |
| private class ProjectEntry |
| { |
| boolean isEnabledCommitted; |
| boolean isEnabled; |
| } |
| } |