/******************************************************************************* * Copyright (c) 2004, 2009 QNX Software Systems 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: * QNX Software Systems - Initial API and implementation * Gaetano Santoro (gaetano.santoro@st.com): patch for * https://bugs.eclipse.org/bugs/show_bug.cgi?id=274499 *******************************************************************************/ package org.eclipse.cdt.debug.internal.core; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; import org.eclipse.cdt.debug.core.CDebugCorePlugin; import org.eclipse.cdt.debug.core.CDebugUtils; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.debug.core.ICGlobalVariableManager; import org.eclipse.cdt.debug.core.model.ICGlobalVariable; import org.eclipse.cdt.debug.core.model.IGlobalVariableDescriptor; import org.eclipse.cdt.debug.internal.core.model.CDebugTarget; import org.eclipse.cdt.debug.internal.core.model.CVariable; import org.eclipse.cdt.debug.internal.core.model.CVariableFactory; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * Manages all global variables registered with a debug target. */ public class CGlobalVariableManager implements ICGlobalVariableManager { private static final String GLOBAL_VARIABLE_LIST = "globalVariableList"; //$NON-NLS-1$ private static final String GLOBAL_VARIABLE = "globalVariable"; //$NON-NLS-1$ private static final String ATTR_GLOBAL_VARIABLE_PATH = "path"; //$NON-NLS-1$ private static final String ATTR_GLOBAL_VARIABLE_NAME = "name"; //$NON-NLS-1$ private CDebugTarget fDebugTarget; private IGlobalVariableDescriptor[] fInitialDescriptors = new IGlobalVariableDescriptor[0]; private List<ICGlobalVariable> fGlobals; /** * Constructor for CGlobalVariableManager. */ public CGlobalVariableManager( CDebugTarget target ) { super(); setDebugTarget( target ); initialize(); } protected CDebugTarget getDebugTarget() { return fDebugTarget; } private void setDebugTarget( CDebugTarget debugTarget ) { fDebugTarget = debugTarget; } public ICGlobalVariable[] getGlobals() { if ( fGlobals == null ) { try { addGlobals( getInitialDescriptors() ); } catch( DebugException e ) { DebugPlugin.log( e ); } } return fGlobals.toArray( new ICGlobalVariable[fGlobals.size()] ); } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.ICGlobalVariableManager#addGlobals(IGlobalVariableDescriptor[]) */ public void addGlobals( IGlobalVariableDescriptor[] descriptors ) throws DebugException { fGlobals = new ArrayList<ICGlobalVariable>( 10 ); MultiStatus ms = new MultiStatus( CDebugCorePlugin.getUniqueIdentifier(), 0, "", null ); //$NON-NLS-1$ List<ICGlobalVariable> globals = new ArrayList<ICGlobalVariable>( descriptors.length ); for ( int i = 0; i < descriptors.length; ++i ) { try { globals.add( getDebugTarget().createGlobalVariable( descriptors[i] ) ); } catch( DebugException e ) { ms.add( e.getStatus() ); } } if ( globals.size() > 0 ) { synchronized( fGlobals ) { fGlobals.addAll( globals ); } } getDebugTarget().fireChangeEvent( DebugEvent.CONTENT ); if ( !ms.isOK() ) { throw new DebugException( ms ); } } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.ICGlobalVariableManager#removeGlobals(ICGlobalVariable[]) */ public void removeGlobals( ICGlobalVariable[] globals ) { synchronized( fGlobals ) { fGlobals.removeAll( Arrays.asList( globals ) ); } for ( int i = 0; i < globals.length; ++i ) { if ( globals[i] instanceof CVariable ) ((CVariable)globals[i]).dispose(); } getDebugTarget().fireChangeEvent( DebugEvent.CONTENT ); } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.ICGlobalVariableManager#removeAllGlobals() */ public void removeAllGlobals() { if (fGlobals == null ) { return; } ICGlobalVariable[] globals; synchronized( fGlobals ) { globals = fGlobals.toArray( new ICGlobalVariable[fGlobals.size()] ); fGlobals.clear(); } for ( int i = 0; i < globals.length; ++i ) { if ( globals[i] instanceof CVariable ) ((CVariable)globals[i]).dispose(); } getDebugTarget().fireChangeEvent( DebugEvent.CONTENT ); } public void dispose() { if ( fGlobals != null ) { for (ICGlobalVariable global : fGlobals) { ((CVariable)global).dispose(); } fGlobals.clear(); fGlobals = null; } } public String getMemento() { Document document = null; try { document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); Element node = document.createElement( GLOBAL_VARIABLE_LIST ); document.appendChild( node ); ICGlobalVariable[] globals = getGlobals(); for (ICGlobalVariable global : globals) { IGlobalVariableDescriptor descriptor = global.getDescriptor(); // children of globals don't have a descriptor, though getGlobals() shouldn't return only top level globals if (descriptor != null) { Element child = document.createElement( GLOBAL_VARIABLE ); child.setAttribute( ATTR_GLOBAL_VARIABLE_NAME, descriptor.getName() ); child.setAttribute( ATTR_GLOBAL_VARIABLE_PATH, descriptor.getPath().toOSString() ); node.appendChild( child ); } } return CDebugUtils.serializeDocument( document ); } catch( ParserConfigurationException e ) { DebugPlugin.log( e ); } catch( IOException e ) { DebugPlugin.log( e ); } catch( TransformerException e ) { DebugPlugin.log( e ); } return null; } private void initializeFromMemento( String memento ) throws CoreException { Exception ex = null; try { Element root = null; DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); StringReader reader = new StringReader( memento ); InputSource source = new InputSource( reader ); root = parser.parse( source ).getDocumentElement(); if ( root.getNodeName().equalsIgnoreCase( GLOBAL_VARIABLE_LIST ) ) { List<IGlobalVariableDescriptor> descriptors = new ArrayList<IGlobalVariableDescriptor>(); NodeList list = root.getChildNodes(); int length = list.getLength(); for( int i = 0; i < length; ++i ) { Node node = list.item( i ); short type = node.getNodeType(); if ( type == Node.ELEMENT_NODE ) { Element entry = (Element)node; if ( entry.getNodeName().equalsIgnoreCase( GLOBAL_VARIABLE ) ) { String name = entry.getAttribute( ATTR_GLOBAL_VARIABLE_NAME ); String pathString = entry.getAttribute( ATTR_GLOBAL_VARIABLE_PATH ); IPath path = new Path( pathString ); if ( path.isValidPath( pathString ) ) { descriptors.add( CVariableFactory.createGlobalVariableDescriptor( name, path ) ); } } } } fInitialDescriptors = descriptors.toArray( new IGlobalVariableDescriptor[descriptors.size()] ); return; } } catch( ParserConfigurationException e ) { ex = e; } catch( SAXException e ) { ex = e; } catch( IOException e ) { ex = e; } abort( InternalDebugCoreMessages.getString( "CGlobalVariableManager.0" ), ex ); //$NON-NLS-1$ } private void initialize() { ILaunchConfiguration config = getDebugTarget().getLaunch().getLaunchConfiguration(); try { String memento = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_GLOBAL_VARIABLES, "" ); //$NON-NLS-1$ if ( memento != null && memento.trim().length() != 0 ) initializeFromMemento( memento ); } catch( CoreException e ) { DebugPlugin.log( e ); } } /** * Throws an internal error exception */ private void abort( String message, Throwable e ) throws CoreException { IStatus s = new Status( IStatus.ERROR, CDebugCorePlugin.getUniqueIdentifier(), CDebugCorePlugin.INTERNAL_ERROR, message, e ); throw new CoreException( s ); } private IGlobalVariableDescriptor[] getInitialDescriptors() { return fInitialDescriptors; } public void save() { ILaunchConfiguration config = getDebugTarget().getLaunch().getLaunchConfiguration(); try { ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy(); wc.setAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_GLOBAL_VARIABLES, getMemento() ); wc.doSave(); } catch( CoreException e ) { DebugPlugin.log( e ); } } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.ICGlobalVariableManager#getDescriptors() */ public IGlobalVariableDescriptor[] getDescriptors() { if ( fGlobals == null ) return getInitialDescriptors(); List<IGlobalVariableDescriptor> descrs = new ArrayList<IGlobalVariableDescriptor>(); for (ICGlobalVariable global : fGlobals) { IGlobalVariableDescriptor descr = global.getDescriptor(); if (descr != null) { // children of globals don't have a descriptor, though 'fGlobals' should contain only top level globals descrs.add(descr); } } return descrs.toArray(new IGlobalVariableDescriptor[descrs.size()]); } }