blob: 853b29e08c5d76fff1e78673f0e4e7115b9d3c30 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2017 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.pde.internal.core.text.bundle;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.pde.internal.core.bundle.BundleObject;
import org.eclipse.pde.internal.core.ibundle.IBundleModel;
import org.osgi.framework.BundleException;
public class PDEManifestElement extends BundleObject {
private static final long serialVersionUID = 1L;
protected String[] fValueComponents;
protected TreeMap<String, Serializable> fAttributes;
protected TreeMap<String, Serializable> fDirectives;
protected transient ManifestHeader fHeader;
public PDEManifestElement(ManifestHeader header, String value) {
setHeader(header);
setValue(value);
setModel(fHeader.getBundle().getModel());
}
protected PDEManifestElement(ManifestHeader header, ManifestElement manifestElement) {
setHeader(header);
init(manifestElement);
setModel(fHeader.getBundle().getModel());
}
public String[] getValueComponents() {
return fValueComponents;
}
protected void setValueComponents(String[] valueComponents) {
fValueComponents = valueComponents;
}
public String[] getAttributes(String key) {
return getTableValues(fAttributes, key);
}
public String getAttribute(String key) {
return getTableValue(fAttributes, key);
}
public Set<String> getKeys() {
return getTableKeys(fAttributes);
}
public void addAttribute(String key, String value) {
fAttributes = addTableValue(fAttributes, key, value);
}
public void setAttribute(String key, String value) {
fAttributes = setTableValue(fAttributes, key, value);
}
public String getDirective(String key) {
return getTableValue(fDirectives, key);
}
public String[] getDirectives(String key) {
return getTableValues(fDirectives, key);
}
public Set<String> getDirectiveKeys() {
return getTableKeys(fDirectives);
}
public void addDirective(String key, String value) {
fDirectives = addTableValue(fDirectives, key, value);
}
public void setDirective(String key, String value) {
fDirectives = setTableValue(fDirectives, key, value);
}
private String getTableValue(TreeMap<String, Serializable> table, String key) {
if (table == null) {
return null;
}
Object result = table.get(key);
if (result == null) {
return null;
}
if (result instanceof String) {
return (String) result;
}
@SuppressWarnings({ "unchecked" })
List<String> valueList = (List<String>) result;
//return the last value
return valueList.get(valueList.size() - 1);
}
private String[] getTableValues(TreeMap<String, Serializable> table, String key) {
if (table == null) {
return null;
}
Object result = table.get(key);
if (result == null) {
return null;
}
if (result instanceof String) {
return new String[] {(String) result};
}
@SuppressWarnings("unchecked")
List<String> valueList = (List<String>) result;
return valueList.toArray(new String[valueList.size()]);
}
private Set<String> getTableKeys(TreeMap<String, Serializable> table) {
if (table == null) {
return null;
}
return table.keySet();
}
@SuppressWarnings("unchecked")
private TreeMap<String, Serializable> addTableValue(TreeMap<String, Serializable> table, String key, String value) {
if (table == null) {
table = new TreeMap<>();
}
Object curValue = table.get(key);
if (curValue != null) {
ArrayList<Object> newList;
// create a list to contain multiple values
if (curValue instanceof ArrayList) {
newList = (ArrayList<Object>) curValue;
} else {
newList = new ArrayList<>(5);
newList.add(curValue);
}
newList.add(value);
table.put(key, newList);
} else {
table.put(key, value);
}
return table;
}
private TreeMap<String, Serializable> setTableValue(TreeMap<String, Serializable> table, String key, String value) {
if (table == null) {
table = new TreeMap<>();
}
if (value == null || value.trim().length() == 0) {
table.remove(key);
} else {
table.put(key, value);
}
return table;
}
public void setValue(String value) {
if (value == null) {
setValueComponents(new String[0]);
return;
}
try {
ManifestElement[] elements = ManifestElement.parseHeader(fHeader.fName, value);
if (elements != null && elements.length > 0) {
init(elements[0]);
}
} catch (BundleException e) {
}
}
private void init(ManifestElement manifestElement) {
setValueComponents(manifestElement.getValueComponents());
Enumeration<String> attKeys = manifestElement.getKeys();
if (attKeys != null) {
while (attKeys.hasMoreElements()) {
String attKey = attKeys.nextElement();
String[] values = ManifestElement.getArrayFromList(manifestElement.getAttribute(attKey));
//empty string in attribute, go with default behavior of attribute
if (values == null) {
continue;
}
for (String value : values) {
addAttribute(attKey, value);
}
}
}
Enumeration<String> dirKeys = manifestElement.getDirectiveKeys();
if (dirKeys != null) {
while (dirKeys.hasMoreElements()) {
String dirKey = dirKeys.nextElement();
String[] values = ManifestElement.getArrayFromList(manifestElement.getDirective(dirKey));
for (String value : values) {
addDirective(dirKey, value);
}
}
}
}
public String write() {
StringBuilder sb = new StringBuilder(getValue());
appendValuesToBuffer(sb, fAttributes);
appendValuesToBuffer(sb, fDirectives);
return sb.toString();
}
public String getValue() {
StringBuilder sb = new StringBuilder();
if (fValueComponents == null) {
return ""; //$NON-NLS-1$
}
for (int i = 0; i < fValueComponents.length; i++) {
if (i != 0) {
sb.append("; "); //$NON-NLS-1$
}
sb.append(fValueComponents[i]);
}
return sb.toString();
}
protected void appendValuesToBuffer(StringBuilder sb, TreeMap<String, Serializable> table) {
if (table == null) {
return;
}
for (Entry<String, Serializable> entry : table.entrySet()) {
String dkey = entry.getKey();
Object value = entry.getValue();
if (value == null) {
continue;
}
sb.append(";"); //$NON-NLS-1$
sb.append(dkey);
sb.append(table.equals(fDirectives) ? ":=" : "="); //$NON-NLS-1$ //$NON-NLS-2$
if (value instanceof String) {
boolean wrap = shouldWrap(value.toString());
if (wrap) {
sb.append("\""); //$NON-NLS-1$
}
sb.append(value);
if (wrap) {
sb.append("\""); //$NON-NLS-1$
}
} else if (value instanceof ArrayList) {
ArrayList<?> values = (ArrayList<?>) value;
boolean wrap = (values.size() > 1 || (values.size() == 1 && shouldWrap(values.get(0).toString())));
if (wrap) {
sb.append("\""); //$NON-NLS-1$
}
for (int i = 0; i < values.size(); i++) {
if (i != 0) {
sb.append(","); //$NON-NLS-1$
}
sb.append(values.get(i));
}
if (wrap) {
sb.append("\""); //$NON-NLS-1$
}
}
}
}
private boolean shouldWrap(String value) {
return value.indexOf(' ') != -1 || value.indexOf(',') != -1 || value.indexOf('.') != -1 || value.indexOf('[') != -1 || value.indexOf('(') != -1;
}
public ManifestHeader getHeader() {
return fHeader;
}
public void setHeader(ManifestHeader header) {
fHeader = header;
}
/**
* @param model
* @param header
*/
public void reconnect(IBundleModel model, ManifestHeader header) {
super.reconnect(model);
// Transient Field: Header
fHeader = header;
}
}