1 /******************************************************************************* 2 * Copyright (c) 2005, 2017 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 * Landmark Graphics Corporation - bug 397183 14 *******************************************************************************/ 15 package org.eclipse.equinox.internal.p2.engine; 16 17 import java.util.*; 18 import java.util.Map.Entry; 19 import org.eclipse.core.runtime.IStatus; 20 import org.eclipse.equinox.p2.engine.spi.*; 21 22 public class ParameterizedProvisioningAction extends ProvisioningAction { 23 private ProvisioningAction action; 24 private Map<String, String> actionParameters; 25 //ActualParameter is used to keep values to which variables have been resolved. 26 //This is especially useful when undoing in the presence of variables that change (e.g. lastResult) 27 private Map<String, Object> actualParameters; 28 private String actionText; 29 ParameterizedProvisioningAction(ProvisioningAction action, Map<String, String> actionParameters, String actionText)30 public ParameterizedProvisioningAction(ProvisioningAction action, Map<String, String> actionParameters, String actionText) { 31 if (action == null || actionParameters == null) 32 throw new IllegalArgumentException(Messages.ParameterizedProvisioningAction_action_or_parameters_null); 33 this.action = action; 34 this.actionParameters = actionParameters; 35 this.actualParameters = new HashMap<>(actionParameters.size()); 36 this.actionText = actionText; 37 } 38 39 @Override execute(Map<String, Object> parameters)40 public IStatus execute(Map<String, Object> parameters) { 41 parameters = processActionParameters(parameters); 42 return action.execute(parameters); 43 } 44 45 @Override undo(Map<String, Object> parameters)46 public IStatus undo(Map<String, Object> parameters) { 47 parameters = processActionParameters(parameters); 48 return action.undo(parameters); 49 } 50 processActionParameters(Map<String, Object> parameters)51 private Map<String, Object> processActionParameters(Map<String, Object> parameters) { 52 Map<String, Object> result = new HashMap<>(parameters); 53 for (Entry<String, String> entry : actionParameters.entrySet()) { 54 String name = entry.getKey(); 55 Object value = processVariables(entry.getValue(), parameters, false); 56 result.put(name, value); 57 } 58 return Collections.unmodifiableMap(result); 59 } 60 61 //allowInfixReplacement triggers the replacement of the variables found in the middle of a string (e.g. abc${var}def) processVariables(String parameterValue, Map<String, Object> parameters, boolean allowInfixReplacement)62 private Object processVariables(String parameterValue, Map<String, Object> parameters, boolean allowInfixReplacement) { 63 int variableBeginIndex = parameterValue.indexOf("${"); //$NON-NLS-1$ 64 if (variableBeginIndex == -1) 65 return parameterValue; 66 67 int variableEndIndex = parameterValue.indexOf('}', variableBeginIndex + 2); 68 if (variableEndIndex == -1) 69 return parameterValue; 70 71 String preVariable = parameterValue.substring(0, variableBeginIndex); 72 String variableName = parameterValue.substring(variableBeginIndex + 2, variableEndIndex); 73 74 //replace the internal name by the user visible name 75 if (Phase.LAST_RESULT_PUBLIC_NAME.equals(variableName)) { 76 variableName = Phase.LAST_RESULT_INTERNAL_NAME; 77 } 78 Object valueUsed = actualParameters.get(variableName); 79 Object value = valueUsed == null ? parameters.get(variableName) : valueUsed; 80 actualParameters.put(variableName, value); 81 82 if (value instanceof Value) { 83 if (allowInfixReplacement == false && variableBeginIndex == 0 && variableEndIndex == parameterValue.length() - 1) { 84 return ((Value<?>) value).getValue(); 85 } 86 87 Value<?> result = (Value<?>) value; 88 if (result.getClazz() == String.class) { 89 value = result.getValue(); 90 } else 91 throw new RuntimeException("The type of the variable is expected to be a String"); //$NON-NLS-1$ 92 } 93 94 // try to replace this parameter with a character 95 if (value == null && variableName.charAt(0) == '#') { 96 try { 97 int code = Integer.parseInt(variableName.substring(1)); 98 if (code >= 0 && code < 65536) 99 value = Character.toString((char) code); 100 } catch (Throwable t) { 101 // ignore and leave value as null 102 } 103 } 104 105 String variableValue = value == null ? "" : value.toString(); //$NON-NLS-1$ //TODO This is where we replace the values 106 String postVariable = (String) processVariables(parameterValue.substring(variableEndIndex + 1), parameters, true); 107 return preVariable + variableValue + postVariable; 108 } 109 getAction()110 public ProvisioningAction getAction() { 111 return action; 112 } 113 getParameters()114 public Map<String, String> getParameters() { 115 return actionParameters; 116 } 117 getActionText()118 public String getActionText() { 119 return actionText; 120 } 121 122 @Override getTouchpoint()123 public Touchpoint getTouchpoint() { 124 return action.getTouchpoint(); 125 } 126 127 @Override setTouchpoint(Touchpoint touchpoint)128 public void setTouchpoint(Touchpoint touchpoint) { 129 throw new UnsupportedOperationException(); 130 } 131 132 @Override getResult()133 public Value<?> getResult() { 134 return action.getResult(); 135 } 136 137 } 138