1 11 package org.eclipse.core.internal.variables; 12 13 import java.io.ByteArrayInputStream ; 14 import java.io.ByteArrayOutputStream ; 15 import java.io.IOException ; 16 import java.io.UnsupportedEncodingException ; 17 import java.util.ArrayList ; 18 import java.util.HashMap ; 19 import java.util.List ; 20 import java.util.Map ; 21 22 import javax.xml.parsers.DocumentBuilder ; 23 import javax.xml.parsers.DocumentBuilderFactory ; 24 import javax.xml.parsers.FactoryConfigurationError ; 25 import javax.xml.parsers.ParserConfigurationException ; 26 import javax.xml.transform.OutputKeys ; 27 import javax.xml.transform.Transformer ; 28 import javax.xml.transform.TransformerException ; 29 import javax.xml.transform.TransformerFactory ; 30 import javax.xml.transform.dom.DOMSource ; 31 import javax.xml.transform.stream.StreamResult ; 32 33 import org.eclipse.core.runtime.CoreException; 34 import org.eclipse.core.runtime.IConfigurationElement; 35 import org.eclipse.core.runtime.IExtensionPoint; 36 import org.eclipse.core.runtime.ISafeRunnable; 37 import org.eclipse.core.runtime.IStatus; 38 import org.eclipse.core.runtime.ListenerList; 39 import org.eclipse.core.runtime.MultiStatus; 40 import org.eclipse.core.runtime.Platform; 41 import org.eclipse.core.runtime.Preferences; 42 import org.eclipse.core.runtime.SafeRunner; 43 import org.eclipse.core.runtime.Status; 44 import org.eclipse.core.runtime.Preferences.IPropertyChangeListener; 45 import org.eclipse.core.runtime.Preferences.PropertyChangeEvent; 46 import org.eclipse.core.variables.IDynamicVariable; 47 import org.eclipse.core.variables.IStringVariable; 48 import org.eclipse.core.variables.IStringVariableManager; 49 import org.eclipse.core.variables.IValueVariable; 50 import org.eclipse.core.variables.IValueVariableListener; 51 import org.eclipse.core.variables.VariablesPlugin; 52 import org.eclipse.osgi.util.NLS; 53 import org.w3c.dom.Document ; 54 import org.w3c.dom.Element ; 55 import org.w3c.dom.Node ; 56 import org.w3c.dom.NodeList ; 57 import org.xml.sax.SAXException ; 58 import org.xml.sax.helpers.DefaultHandler ; 59 60 63 public class StringVariableManager implements IStringVariableManager, IPropertyChangeListener { 64 65 68 private Map fDynamicVariables; 69 70 73 private Map fValueVariables; 74 75 78 private ListenerList fListeners; 79 80 private static final int ADDED = 0; 82 private static final int CHANGED = 1; 83 private static final int REMOVED = 2; 84 85 88 private static StringVariableManager fgManager; 89 90 private boolean fInternalChange = false; 93 94 private static final String ATTR_NAME= "name"; private static final String ATTR_DESCRIPTION="description"; private static final String ATTR_READ_ONLY="readOnly"; private static final String VALUE_VARIABLES_TAG= "valueVariables"; private static final String VALUE_VARIABLE_TAG= "valueVariable"; private static final String NAME_TAG= "name"; private static final String VALUE_TAG= "value"; private static final String DESCRIPTION_TAG="description"; private static final String READ_ONLY_TAG="readOnly"; private static final String TRUE_VALUE= "true"; private static final String FALSE_VALUE= "false"; private static final String PREF_VALUE_VARIABLES= VariablesPlugin.getUniqueIdentifier() + ".valueVariables"; 111 115 class StringVariableNotifier implements ISafeRunnable { 116 117 private IValueVariableListener fListener; 118 private int fType; 119 private IValueVariable[] fVariables; 120 121 124 public void handleException(Throwable exception) { 125 IStatus status = new Status(IStatus.ERROR, VariablesPlugin.getUniqueIdentifier(), VariablesPlugin.INTERNAL_ERROR, "An exception occurred during string variable change notification", exception); VariablesPlugin.log(status); 127 } 128 129 132 public void run() throws Exception { 133 switch (fType) { 134 case ADDED: 135 fListener.variablesAdded(fVariables); 136 break; 137 case REMOVED: 138 fListener.variablesRemoved(fVariables); 139 break; 140 case CHANGED: 141 fListener.variablesChanged(fVariables); 142 break; 143 } 144 } 145 146 153 public void notify(IValueVariable[] variables, int update) { 154 fVariables = variables; 155 fType = update; 156 Object [] copiedListeners= fListeners.getListeners(); 157 for (int i= 0; i < copiedListeners.length; i++) { 158 fListener = (IValueVariableListener)copiedListeners[i]; 159 SafeRunner.run(this); 160 } 161 fVariables = null; 162 fListener = null; 163 storeValueVariables(); 165 } 166 } 167 168 173 private StringVariableNotifier getNotifier() { 174 return new StringVariableNotifier(); 175 } 176 177 182 public static StringVariableManager getDefault() { 183 if (fgManager == null) { 184 fgManager = new StringVariableManager(); 185 } 186 return fgManager; 187 } 188 189 192 private StringVariableManager() { 193 fListeners = new ListenerList(); 194 } 195 196 199 private synchronized void initialize() { 200 if (fDynamicVariables == null) { 201 fInternalChange = true; 202 fDynamicVariables = new HashMap (5); 203 fValueVariables = new HashMap (5); 204 loadContributedValueVariables(); 205 loadPersistedValueVariables(); 206 loadDynamicVariables(); 207 VariablesPlugin.getDefault().getPluginPreferences().addPropertyChangeListener(this); 208 fInternalChange = false; 209 } 210 } 211 212 215 private void loadDynamicVariables() { 216 IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(VariablesPlugin.PI_CORE_VARIABLES, EXTENSION_POINT_DYNAMIC_VARIABLES); 217 IConfigurationElement elements[]= point.getConfigurationElements(); 218 for (int i = 0; i < elements.length; i++) { 219 IConfigurationElement element = elements[i]; 220 String name= element.getAttribute(ATTR_NAME); 221 if (name == null) { 222 VariablesPlugin.logMessage(NLS.bind("Variable extension missing required 'name' attribute: {0}", new String [] {element.getDeclaringExtension().getLabel()}), null); continue; 224 } 225 String description= element.getAttribute(ATTR_DESCRIPTION); 226 DynamicVariable variable= new DynamicVariable(name, description, element); 227 fDynamicVariables.put(variable.getName(), variable); 228 } 229 } 230 231 234 private void loadContributedValueVariables() { 235 IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(VariablesPlugin.PI_CORE_VARIABLES, EXTENSION_POINT_VALUE_VARIABLES); 236 IConfigurationElement elements[]= point.getConfigurationElements(); 237 for (int i = 0; i < elements.length; i++) { 238 IConfigurationElement element = elements[i]; 239 String name= element.getAttribute(ATTR_NAME); 240 if (name == null) { 241 VariablesPlugin.logMessage(NLS.bind("Variable extension missing required 'name' attribute: {0}", new String [] {element.getDeclaringExtension().getLabel()}), null); continue; 243 } 244 String description= element.getAttribute(ATTR_DESCRIPTION); 245 boolean isReadOnly = TRUE_VALUE.equals(element.getAttribute(ATTR_READ_ONLY)); 246 247 IValueVariable variable = new ContributedValueVariable(name, description, isReadOnly, element); 248 fValueVariables.put(name, variable); 249 } 250 } 251 252 259 private void loadPersistedValueVariables() { 260 String variablesString= VariablesPlugin.getDefault().getPluginPreferences().getString(PREF_VALUE_VARIABLES); 261 if (variablesString.length() == 0) { 262 return; 263 } 264 Element root= null; 265 Throwable ex = null; 266 try { 267 ByteArrayInputStream stream = new ByteArrayInputStream (variablesString.getBytes("UTF-8")); DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 269 parser.setErrorHandler(new DefaultHandler ()); 270 root = parser.parse(stream).getDocumentElement(); 271 } catch (UnsupportedEncodingException e) { 272 ex = e; 273 } catch (ParserConfigurationException e) { 274 ex = e; 275 } catch (FactoryConfigurationError e) { 276 ex = e; 277 } catch (SAXException e) { 278 ex = e; 279 } catch (IOException e) { 280 ex = e; 281 } 282 if (ex != null) { 283 VariablesPlugin.logMessage("An exception occurred while loading persisted value variables.", ex); return; 285 } 286 if (!root.getNodeName().equals(VALUE_VARIABLES_TAG)) { 287 VariablesPlugin.logMessage("Invalid format encountered while loading persisted value variables.", null); return; 289 } 290 NodeList list= root.getChildNodes(); 291 for (int i= 0, numItems= list.getLength(); i < numItems; i++) { 292 Node node= list.item(i); 293 if (node.getNodeType() == Node.ELEMENT_NODE) { 294 Element element= (Element) node; 295 if (!element.getNodeName().equals(VALUE_VARIABLE_TAG)) { 296 VariablesPlugin.logMessage(NLS.bind("Invalid XML element encountered while loading value variables: {0}", new String [] {node.getNodeName()}), null); continue; 298 } 299 String name= element.getAttribute(NAME_TAG); 300 if (name.length() > 0) { 301 String value= element.getAttribute(VALUE_TAG); 302 String description= element.getAttribute(DESCRIPTION_TAG); 303 boolean readOnly= TRUE_VALUE.equals(element.getAttribute(READ_ONLY_TAG)); 304 305 IValueVariable existing = getValueVariable(name); 306 if (existing == null){ 307 ValueVariable variable = new ValueVariable(name, description, readOnly, value); 308 fValueVariables.put(name, variable); 309 } else if (!existing.isReadOnly() && value != null){ 310 existing.setValue(value); 311 } 312 } else { 313 VariablesPlugin.logMessage("Invalid variable entry encountered while loading value variables. Variable name is null.", null); } 315 } 316 } 317 } 318 319 322 public synchronized IStringVariable[] getVariables() { 323 initialize(); 324 List list = new ArrayList (fDynamicVariables.size() + fValueVariables.size()); 325 list.addAll(fDynamicVariables.values()); 326 list.addAll(fValueVariables.values()); 327 return (IStringVariable[]) list.toArray(new IStringVariable[list.size()]); 328 } 329 330 333 public synchronized IValueVariable[] getValueVariables() { 334 initialize(); 335 return (IValueVariable[]) fValueVariables.values().toArray(new IValueVariable[fValueVariables.size()]); 336 } 337 338 341 public synchronized IDynamicVariable[] getDynamicVariables() { 342 initialize(); 343 return (IDynamicVariable[]) fDynamicVariables.values().toArray(new IDynamicVariable[fDynamicVariables.size()]); 344 } 345 346 349 public String performStringSubstitution(String expression) throws CoreException { 350 return performStringSubstitution(expression, true); 351 } 352 353 356 public IValueVariable newValueVariable(String name, String description) { 357 return newValueVariable(name, description, false, null); 358 } 359 360 363 public IValueVariable newValueVariable(String name, String description, boolean readOnly, String value) { 364 return new ValueVariable(name, description, readOnly, value); 365 } 366 367 370 public synchronized void addVariables(IValueVariable[] variables) throws CoreException { 371 initialize(); 372 MultiStatus status = new MultiStatus(VariablesPlugin.getUniqueIdentifier(), VariablesPlugin.INTERNAL_ERROR, VariablesMessages.StringVariableManager_26, null); 373 for (int i = 0; i < variables.length; i++) { 374 IValueVariable variable = variables[i]; 375 if (getValueVariable(variable.getName()) != null) { 376 status.add(new Status(IStatus.ERROR, VariablesPlugin.getUniqueIdentifier(), VariablesPlugin.INTERNAL_ERROR, NLS.bind(VariablesMessages.StringVariableManager_27, new String []{variable.getName()}), null)); 377 } 378 } 379 if (status.isOK()) { 380 for (int i = 0; i < variables.length; i++) { 381 IValueVariable variable = variables[i]; 382 fValueVariables.put(variable.getName(), variable); 383 } 384 IValueVariable[] copy = new IValueVariable[variables.length]; 385 System.arraycopy(variables, 0, copy, 0, variables.length); 386 getNotifier().notify(copy, ADDED); 387 return; 388 } 389 throw new CoreException(status); 390 } 391 392 395 public synchronized void removeVariables(IValueVariable[] variables) { 396 initialize(); 397 List removed = new ArrayList (variables.length); 398 for (int i = 0; i < variables.length; i++) { 399 IValueVariable variable = variables[i]; 400 if (fValueVariables.remove(variable.getName()) != null) { 401 removed.add(variable); 402 } 403 } 404 if (removed.size() > 0) { 405 getNotifier().notify((IValueVariable[])removed.toArray(new IValueVariable[removed.size()]), REMOVED); 406 } 407 } 408 409 412 public synchronized IDynamicVariable getDynamicVariable(String name) { 413 initialize(); 414 return (IDynamicVariable) fDynamicVariables.get(name); 415 } 416 417 420 public synchronized IValueVariable getValueVariable(String name) { 421 initialize(); 422 return (IValueVariable) fValueVariables.get(name); 423 } 424 425 426 429 public void addValueVariableListener(IValueVariableListener listener) { 430 fListeners.add(listener); 431 } 432 433 436 public void removeValueVariableListener(IValueVariableListener listener) { 437 fListeners.remove(listener); 438 } 439 440 446 private String getValueVariablesAsXML() throws IOException , ParserConfigurationException , TransformerException { 447 IValueVariable[] variables = getValueVariables(); 448 449 Document document= getDocument(); 450 Element rootElement= document.createElement(VALUE_VARIABLES_TAG); 451 document.appendChild(rootElement); 452 for (int i = 0; i < variables.length; i++) { 453 IValueVariable variable = variables[i]; 454 if (!variable.isReadOnly()){ 455 if (!variable.isContributed() || ((ContributedValueVariable)variable).isInitialized()) { 457 Element element= document.createElement(VALUE_VARIABLE_TAG); 458 element.setAttribute(NAME_TAG, variable.getName()); 459 String value= variable.getValue(); 460 if (value != null) { 461 element.setAttribute(VALUE_TAG, value); 462 } 463 element.setAttribute(READ_ONLY_TAG, variable.isReadOnly() ? TRUE_VALUE : FALSE_VALUE); 464 String description= variable.getDescription(); 465 if (description != null) { 466 element.setAttribute(DESCRIPTION_TAG, description); 467 } 468 rootElement.appendChild(element); 469 } 470 } 471 } 472 return serializeDocument(document); 473 } 474 475 private Document getDocument() throws ParserConfigurationException { 476 DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); 477 DocumentBuilder docBuilder = dfactory.newDocumentBuilder(); 478 Document doc =docBuilder.newDocument(); 479 return doc; 480 } 481 482 491 private String serializeDocument(Document doc) throws TransformerException , UnsupportedEncodingException { 492 ByteArrayOutputStream s= new ByteArrayOutputStream (); 493 494 TransformerFactory factory= TransformerFactory.newInstance(); 495 Transformer transformer= factory.newTransformer(); 496 transformer.setOutputProperty(OutputKeys.METHOD, "xml"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 499 DOMSource source= new DOMSource (doc); 500 StreamResult outputTarget= new StreamResult (s); 501 transformer.transform(source, outputTarget); 502 503 return s.toString("UTF8"); } 505 506 510 private synchronized void storeValueVariables() { 511 Preferences prefs= VariablesPlugin.getDefault().getPluginPreferences(); 512 String variableString= ""; if (!fValueVariables.isEmpty()) { 514 try { 515 variableString= getValueVariablesAsXML(); 516 } catch (IOException e) { 517 VariablesPlugin.log(new Status(IStatus.ERROR, VariablesPlugin.getUniqueIdentifier(), IStatus.ERROR, "An exception occurred while storing launch configuration variables.", e)); return; 519 } catch (ParserConfigurationException e) { 520 VariablesPlugin.log(new Status(IStatus.ERROR, VariablesPlugin.getUniqueIdentifier(), IStatus.ERROR, "An exception occurred while storing launch configuration variables.", e)); return; 522 } catch (TransformerException e) { 523 VariablesPlugin.log(new Status(IStatus.ERROR, VariablesPlugin.getUniqueIdentifier(), IStatus.ERROR, "An exception occurred while storing launch configuration variables.", e)); return; 525 } 526 } 527 fInternalChange = true; 528 prefs.setValue(PREF_VALUE_VARIABLES, variableString); 529 VariablesPlugin.getDefault().savePluginPreferences(); 530 fInternalChange = false; 531 } 532 533 538 protected void notifyChanged(IValueVariable variable) { 539 if (!fInternalChange) { 540 IValueVariable existing = getValueVariable(variable.getName()); 541 if (variable.equals(existing)) { 542 getNotifier().notify(new IValueVariable[]{variable}, CHANGED); 544 } 545 } 546 } 547 548 551 public String generateVariableExpression(String varName, String arg) { 552 StringBuffer buffer = new StringBuffer (); 553 buffer.append("${"); buffer.append(varName); 555 if (arg != null) { 556 buffer.append(":"); buffer.append(arg); 558 } 559 buffer.append("}"); return buffer.toString(); 561 } 562 563 566 public String performStringSubstitution(String expression, boolean reportUndefinedVariables) throws CoreException { 567 return new StringSubstitutionEngine().performStringSubstitution(expression, reportUndefinedVariables, true, this); 568 } 569 570 573 public void validateStringVariables(String expression) throws CoreException { 574 new StringSubstitutionEngine().validateStringVariables(expression, this); 575 } 576 577 580 public String getContributingPluginId(IStringVariable variable) { 581 if (variable instanceof StringVariable) { 582 return ((StringVariable) variable).getConfigurationElement().getContributor().getName(); 583 } 584 return null; 585 } 586 587 590 public void propertyChange(PropertyChangeEvent event) { 591 if (PREF_VALUE_VARIABLES.equals(event.getProperty())) { 592 synchronized (this) { 593 if (!fInternalChange) { 594 fValueVariables.clear(); 595 loadPersistedValueVariables(); 596 loadContributedValueVariables(); 597 } 598 } 599 } 600 } 601 } 602 | Popular Tags |