blob: 4db14184750afe3801c97b4c282364ba1fdb875d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 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
*******************************************************************************/
package org.eclipse.equinox.p2.installregistry;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.equinox.internal.p2.engine.EngineActivator;
import org.eclipse.equinox.internal.p2.engine.Messages;
import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
import org.eclipse.equinox.p2.core.eventbus.ProvisioningEventBus;
import org.eclipse.equinox.p2.core.eventbus.SynchronousProvisioningListener;
import org.eclipse.equinox.p2.core.helpers.*;
import org.eclipse.equinox.p2.core.location.AgentLocation;
import org.eclipse.equinox.p2.engine.*;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.osgi.service.resolver.VersionRange;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
import org.xml.sax.*;
public class InstallRegistry implements IInstallRegistry {
private static String STORAGE = "installRegistry.xml"; //$NON-NLS-1$
// what is installed in each profile
private Map profileRegistries = new LinkedHashMap(); // Profile id -> ProfileInstallRegistry
// private ProfileRegistry profileRegistry; // the corresponding ProfileRegistry
// private File location; // XML file containing install registry
// private IRepository metadataRepo;
// private final MetadataCache installedMetadata = new MetadataCache(
// new RepositoryGroup("InstallRegistry"), //$NON-NLS-1$
// MetadataCache.POLICY_NONE);
private transient ServiceReference busReference;
private transient ProvisioningEventBus bus;
public InstallRegistry() {
busReference = EngineActivator.getContext().getServiceReference(ProvisioningEventBus.class.getName());
bus = (ProvisioningEventBus) EngineActivator.getContext().getService(busReference);
restore();
bus.addListener(new SynchronousProvisioningListener() {
public void notify(EventObject o) {
if (o instanceof InstallableUnitEvent) {
InstallableUnitEvent event = (InstallableUnitEvent) o;
if (event.isPre() || !event.getResult().isOK())
return;
IProfileInstallRegistry registry = getProfileInstallRegistry(event.getProfile());
if (event.isInstall() && event.getOperand().second() != null) {
registry.addInstallableUnits(event.getOperand().second().getOriginal());
} else if (event.isUninstall() && event.getOperand().first() != null) {
IInstallableUnit original = event.getOperand().first().getOriginal();
String value = registry.getInstallableUnitProfileProperty(original, IInstallableUnitConstants.PROFILE_ROOT_IU);
boolean isRoot = value != null && value.equals(Boolean.toString(true));
registry.removeInstallableUnits(original);
// TODO this is odd because I'm setting up a property for something
// not yet installed in the registry. The implementation allows it and
// the assumption is that the second operand will get installed or else
// this change will never be committed. The alternative is to remember
// a transitory root value that we set when the install is received.
// The ideal solution is that this is handled in a profile delta by
// the engine.
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=206077
if (isRoot && event.getOperand().second() != null) {
registry.setInstallableUnitProfileProperty(event.getOperand().second().getOriginal(), IInstallableUnitConstants.PROFILE_ROOT_IU, Boolean.toString(true));
}
}
} else if (o instanceof CommitOperationEvent) {
persist();
return;
} else if (o instanceof RollbackOperationEvent) {
restore();
return;
} else if (o instanceof ProfileEvent) {
ProfileEvent pe = (ProfileEvent) o;
if (pe.getReason() == ProfileEvent.REMOVED) {
profileRegistries.remove(pe.getProfile().getProfileId());
persist();
} else if (pe.getReason() == ProfileEvent.CHANGED) {
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=197701
persist();
}
}
}
});
}
private void persist() {
try {
BufferedOutputStream bof = null;
try {
URL registryLocation = getRegistryLocation();
if (!registryLocation.getProtocol().equals("file")) //$NON-NLS-1$
throw new IOException("Can't write install registry at: " + registryLocation);
File outputFile = new File(registryLocation.toExternalForm().substring(5));
if (!outputFile.getParentFile().exists() && !outputFile.getParentFile().mkdirs())
throw new RuntimeException("Can't persist profile registry");
bof = new BufferedOutputStream(new FileOutputStream(outputFile, false));
//new XStream().toXML(profileRegistries, bof);
Writer writer = new Writer(bof);
writer.write(this);
} finally {
if (bof != null)
bof.close();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void restore() {
try {
BufferedInputStream bif = null;
try {
bif = new BufferedInputStream(getRegistryLocation().openStream());
// profileRegistries = (HashMap) new XStream().fromXML(bif);
Parser parser = new Parser(EngineActivator.getContext(), EngineActivator.ID);
parser.parse(bif);
profileRegistries = parser.getProfileInstallRegistries();
} finally {
if (bif != null)
bif.close();
}
} catch (FileNotFoundException e) {
//This is ok.
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public IProfileInstallRegistry getProfileInstallRegistry(Profile profile) {
String profileId = profile.getProfileId();
IProfileInstallRegistry result = (IProfileInstallRegistry) this.profileRegistries.get(profileId);
if (result == null) {
result = new ProfileInstallRegistry(profileId);
this.profileRegistries.put(profileId, result);
}
return result;
}
public Collection getProfileInstallRegistries() {
return this.profileRegistries.values();
}
public InstallRegistry getInstallRegistry() {
return this;
}
private URL getRegistryLocation() {
AgentLocation agent = (AgentLocation) ServiceHelper.getService(EngineActivator.getContext(), AgentLocation.class.getName());
try {
return new URL(agent.getDataArea(EngineActivator.ID), STORAGE);
} catch (MalformedURLException e) {
//this is not possible because we know the above URL is valid
}
return null;
}
protected class IUIdentity {
private String id;
private Version version;
public IUIdentity(String id, Version version) {
this.id = (id != null ? id : ""); //$NON-NLS-1$
this.version = (version != null ? version : Version.emptyVersion);
}
public IUIdentity(IInstallableUnit iu) {
this(iu.getId(), iu.getVersion());
}
public String toString() {
return id + ' ' + version;
}
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((version == null) ? 0 : version.hashCode());
return result;
}
public boolean equals(Object obj) {
final IUIdentity objAsIdentity = //
(obj instanceof IUIdentity ? (IUIdentity) obj : null);
if (objAsIdentity != null) {
return this.id.equals(objAsIdentity.id) && this.version.equals(objAsIdentity.version);
}
return false;
}
}
/**
* Install registry for a single profile.
*/
public class ProfileInstallRegistry implements IProfileInstallRegistry {
private String profileId; // id profile this data applies to
private Set installableUnits; //id
private Map iuPropertiesMap; // iu->OrderedProperties
public ProfileInstallRegistry(String profileId) {
this.profileId = profileId;
this.installableUnits = new LinkedHashSet();
this.iuPropertiesMap = new LinkedHashMap();
}
protected ProfileInstallRegistry(String profileId, IInstallableUnit[] units, Map iuPropertiesMap) {
this.profileId = profileId;
this.installableUnits = new LinkedHashSet(units.length);
this.iuPropertiesMap = new LinkedHashMap(iuPropertiesMap.size());
addInstallableUnits(units);
this.iuPropertiesMap.putAll(iuPropertiesMap);
}
public IInstallableUnit[] getInstallableUnits() {
IInstallableUnit[] result = new IInstallableUnit[installableUnits.size()];
return (IInstallableUnit[]) installableUnits.toArray(result);
}
public void addInstallableUnits(IInstallableUnit toAdd) {
installableUnits.add(toAdd);
}
public void addInstallableUnits(IInstallableUnit[] toAdd) {
for (int i = 0; i < toAdd.length; i++) {
installableUnits.add(toAdd[i]);
}
}
public void removeInstallableUnits(IInstallableUnit toRemove) {
installableUnits.remove(toRemove);
iuPropertiesMap.remove(new IUIdentity(toRemove));
}
public String getProfileId() {
return profileId;
}
public IInstallableUnit getInstallableUnit(String id, String version) {
for (Iterator i = installableUnits.iterator(); i.hasNext();) {
IInstallableUnit iu = (IInstallableUnit) i.next();
if (iu.getId().equals(id) && iu.getVersion().equals(new Version(version)))
return iu;
}
return null;
}
public String getInstallableUnitProfileProperty(IInstallableUnit toGet, String key) {
OrderedProperties properties = getInstallableUnitProfileProperties(toGet);
return properties.getProperty(key);
}
public String setInstallableUnitProfileProperty(IInstallableUnit toSet, String key, String value) {
OrderedProperties properties = getInstallableUnitProfileProperties(toSet);
return (String) properties.setProperty(key, value);
}
private OrderedProperties getInstallableUnitProfileProperties(IInstallableUnit toGet) {
OrderedProperties properties = (OrderedProperties) iuPropertiesMap.get(new IUIdentity(toGet));
if (properties == null) {
properties = new OrderedProperties();
iuPropertiesMap.put(new IUIdentity(toGet), properties);
}
return properties;
}
public Map getIUIdentityToPropertiesMap() {
return Collections.unmodifiableMap(iuPropertiesMap);
}
}
private interface XMLConstants extends org.eclipse.equinox.p2.core.helpers.XMLConstants {
// Constants defining the structure of the XML for a SimpleProfileRegistry
// A format version number for install registry XML.
public static final String XML_VERSION = "0.0.1"; //$NON-NLS-1$
public static final Version CURRENT_VERSION = new Version(XML_VERSION);
public static final VersionRange XML_TOLERANCE = new VersionRange(CURRENT_VERSION, true, CURRENT_VERSION, true);
// Constants for processing instructions
public static final String PI_REPOSITORY_TARGET = "installRegistry"; //$NON-NLS-1$
public static XMLWriter.ProcessingInstruction[] PI_DEFAULTS = new XMLWriter.ProcessingInstruction[] {XMLWriter.ProcessingInstruction.makeClassVersionInstruction(PI_REPOSITORY_TARGET, SimpleProfileRegistry.class, CURRENT_VERSION)};
// Constants for install registry elements
public static final String INSTALL_REGISTRY_ELEMENT = "installRegistry"; //$NON-NLS-1$
public static final String PROFILE_INSTALL_REGISTRIES_ELEMENT = "profiles"; //$NON-NLS-1$
public static final String PROFILE_INSTALL_REGISTRY_ELEMENT = "profile"; //$NON-NLS-1$
public static final String INSTALLABLE_UNITS_ELEMENT = "units"; //$NON-NLS-1$
public static final String INSTALLABLE_UNIT_ELEMENT = "unit"; //$NON-NLS-1$
public static final String IUS_PROPERTIES_ELEMENT = "iusPropertiesMap"; //$NON-NLS-1$
public static final String IU_PROPERTIES_ELEMENT = "iusProperties"; //$NON-NLS-1$
// Constants for attributes of an profile install registry element
public static final String PROFILE_ID_ATTRIBUTE = "profileId"; //$NON-NLS-1$
// Constants for sub-elements of an installable unit element
public static final String ARTIFACT_KEYS_ELEMENT = "artifacts"; //$NON-NLS-1$
public static final String ARTIFACT_KEY_ELEMENT = "artifact"; //$NON-NLS-1$
public static final String REQUIRED_CAPABILITIES_ELEMENT = "requires"; //$NON-NLS-1$
public static final String REQUIRED_CAPABILITY_ELEMENT = "required"; //$NON-NLS-1$
public static final String PROVIDED_CAPABILITIES_ELEMENT = "provides"; //$NON-NLS-1$
public static final String PROVIDED_CAPABILITY_ELEMENT = "provided"; //$NON-NLS-1$
public static final String TOUCHPOINT_TYPE_ELEMENT = "touchpoint"; //$NON-NLS-1$
public static final String TOUCHPOINT_DATA_ELEMENT = "touchpointData"; //$NON-NLS-1$
public static final String IU_FILTER_ELEMENT = "filter"; //$NON-NLS-1$
public static final String APPLICABILITY_FILTER_ELEMENT = "applicability"; //$NON-NLS-1$
// Constants for attributes of an installable unit element
public static final String SINGLETON_ATTRIBUTE = "singleton"; //$NON-NLS-1$
public static final String FRAGMENT_ATTRIBUTE = "fragment"; //$NON-NLS-1$
// Constants for attributes of a fragment installable unit element
public static final String FRAGMENT_HOST_ID_ATTRIBUTE = "hostId"; //$NON-NLS-1$
public static final String FRAGMENT_HOST_RANGE_ATTRIBUTE = "hostRange"; //$NON-NLS-1$
// Constants for sub-elements of a required capability element
public static final String CAPABILITY_FILTER_ELEMENT = "filter"; //$NON-NLS-1$
public static final String CAPABILITY_SELECTORS_ELEMENT = "selectors"; //$NON-NLS-1$
public static final String CAPABILITY_SELECTOR_ELEMENT = "selector"; //$NON-NLS-1$
// Constants for attributes of a required capability element
public static final String CAPABILITY_OPTIONAL_ATTRIBUTE = "optional"; //$NON-NLS-1$
public static final String CAPABILITY_MULTIPLE_ATTRIBUTE = "multiple"; //$NON-NLS-1$
// Constants for attributes of an artifact key element
public static final String ARTIFACT_KEY_NAMESPACE_ATTRIBUTE = NAMESPACE_ATTRIBUTE;
public static final String ARTIFACT_KEY_CLASSIFIER_ATTRIBUTE = "classifier"; //$NON-NLS-1$
// Constants for sub-elements of a touchpoint data element
public static final String TOUCHPOINT_DATA_INSTRUCTIONS_ELEMENT = "instructions"; //$NON-NLS-1$
public static final String TOUCHPOINT_DATA_INSTRUCTION_ELEMENT = "instruction"; //$NON-NLS-1$
// Constants for attributes of an a touchpoint data instruction element
public static final String TOUCHPOINT_DATA_INSTRUCTION_KEY_ATTRIBUTE = "key"; //$NON-NLS-1$
}
protected class Writer extends XMLWriter implements XMLConstants {
public Writer(OutputStream output) throws IOException {
super(output, PI_DEFAULTS);
}
/**
* Write the given artifact repository to the output stream.
*/
public void write(InstallRegistry istregistryry) {
start(INSTALL_REGISTRY_ELEMENT);
writeProfileRegistries(istregistryry.profileRegistries);
end(INSTALL_REGISTRY_ELEMENT);
flush();
}
private void writeProfileRegistries(Map profileRegistries) {
if (profileRegistries.size() > 0) {
start(PROFILE_INSTALL_REGISTRIES_ELEMENT);
attribute(COLLECTION_SIZE_ATTRIBUTE, profileRegistries.size());
for (Iterator iter = profileRegistries.keySet().iterator(); iter.hasNext();) {
String nextProfileId = (String) iter.next();
ProfileInstallRegistry nextProfileRegistry = (ProfileInstallRegistry) profileRegistries.get(nextProfileId);
writeProfileRegistry(nextProfileId, nextProfileRegistry);
}
end(PROFILE_INSTALL_REGISTRIES_ELEMENT);
}
}
private void writeProfileRegistry(String profileId, ProfileInstallRegistry profileRegistry) {
start(PROFILE_INSTALL_REGISTRY_ELEMENT);
attribute(PROFILE_ID_ATTRIBUTE, profileId);
Set ius = profileRegistry.installableUnits;
writeInstallableUnits((IInstallableUnit[]) ius.toArray(new IInstallableUnit[ius.size()]));
writeIUPropertyMap(profileRegistry.getIUIdentityToPropertiesMap());
end(PROFILE_INSTALL_REGISTRY_ELEMENT);
}
private void writeIUPropertyMap(Map iuPropertiesMap) {
if (iuPropertiesMap.size() > 0) {
start(IUS_PROPERTIES_ELEMENT);
attribute(COLLECTION_SIZE_ATTRIBUTE, iuPropertiesMap.size());
for (Iterator iter = iuPropertiesMap.keySet().iterator(); iter.hasNext();) {
IUIdentity nextIdentity = (IUIdentity) iter.next();
OrderedProperties properties = (OrderedProperties) iuPropertiesMap.get(nextIdentity);
start(IU_PROPERTIES_ELEMENT);
attribute(ID_ATTRIBUTE, nextIdentity.id);
attribute(VERSION_ATTRIBUTE, nextIdentity.version);
writeProperties(properties);
end(IU_PROPERTIES_ELEMENT);
}
end(IUS_PROPERTIES_ELEMENT);
}
}
// TODO: below is a LOT of code duplicated for MetadataRepositoryIO for writing
// installable units. Need to figure out a cleanway to declare handlers
// which do not depend on the context of an outer declaring Parser class,
// so that handlers may be reused in different parsing contexts.
private void writeInstallableUnits(IInstallableUnit[] installableUnits) {
if (installableUnits.length > 0) {
start(INSTALLABLE_UNITS_ELEMENT);
attribute(COLLECTION_SIZE_ATTRIBUTE, installableUnits.length);
for (int i = 0; i < installableUnits.length; i++) {
writeInstallableUnit(installableUnits[i]);
}
end(INSTALLABLE_UNITS_ELEMENT);
}
}
private void writeInstallableUnit(IInstallableUnit resolvedIU) {
IInstallableUnit iu = (!(resolvedIU instanceof IResolvedInstallableUnit) ? resolvedIU//
: ((IResolvedInstallableUnit) resolvedIU).getOriginal());
start(INSTALLABLE_UNIT_ELEMENT);
attribute(ID_ATTRIBUTE, iu.getId());
attribute(VERSION_ATTRIBUTE, iu.getVersion());
attribute(SINGLETON_ATTRIBUTE, iu.isSingleton(), true);
attribute(FRAGMENT_ATTRIBUTE, iu.isFragment(), false);
if (iu.isFragment() && iu instanceof IInstallableUnitFragment) {
IInstallableUnitFragment fragment = (IInstallableUnitFragment) iu;
attribute(FRAGMENT_HOST_ID_ATTRIBUTE, fragment.getHostId());
attribute(FRAGMENT_HOST_RANGE_ATTRIBUTE, fragment.getHostVersionRange());
}
writeProperties(iu.getProperties());
writeProvidedCapabilities(iu.getProvidedCapabilities());
writeRequiredCapabilities(iu.getRequiredCapabilities());
writeTrimmedCdata(IU_FILTER_ELEMENT, iu.getFilter());
writeTrimmedCdata(APPLICABILITY_FILTER_ELEMENT, iu.getApplicabilityFilter());
writeArtifactKeys(iu.getArtifacts());
writeTouchpointType(iu.getTouchpointType());
writeTouchpointData(iu.getTouchpointData());
end(INSTALLABLE_UNIT_ELEMENT);
}
private void writeProvidedCapabilities(ProvidedCapability[] capabilities) {
if (capabilities != null && capabilities.length > 0) {
start(PROVIDED_CAPABILITIES_ELEMENT);
attribute(COLLECTION_SIZE_ATTRIBUTE, capabilities.length);
for (int i = 0; i < capabilities.length; i++) {
start(PROVIDED_CAPABILITY_ELEMENT);
attribute(NAMESPACE_ATTRIBUTE, capabilities[i].getNamespace());
attribute(NAME_ATTRIBUTE, capabilities[i].getName());
attribute(VERSION_ATTRIBUTE, capabilities[i].getVersion());
end(PROVIDED_CAPABILITY_ELEMENT);
}
end(PROVIDED_CAPABILITIES_ELEMENT);
}
}
private void writeRequiredCapabilities(RequiredCapability[] capabilities) {
if (capabilities != null && capabilities.length > 0) {
start(REQUIRED_CAPABILITIES_ELEMENT);
attribute(COLLECTION_SIZE_ATTRIBUTE, capabilities.length);
for (int i = 0; i < capabilities.length; i++) {
writeRequiredCapability(capabilities[i]);
}
end(REQUIRED_CAPABILITIES_ELEMENT);
}
}
private void writeRequiredCapability(RequiredCapability capability) {
start(REQUIRED_CAPABILITY_ELEMENT);
attribute(NAMESPACE_ATTRIBUTE, capability.getNamespace());
attribute(NAME_ATTRIBUTE, capability.getName());
attribute(VERSION_RANGE_ATTRIBUTE, capability.getRange());
attribute(CAPABILITY_OPTIONAL_ATTRIBUTE, capability.isOptional(), false);
attribute(CAPABILITY_MULTIPLE_ATTRIBUTE, capability.isMultiple(), false);
writeTrimmedCdata(CAPABILITY_FILTER_ELEMENT, capability.getFilter());
String[] selectors = capability.getSelectors();
if (selectors.length > 0) {
start(CAPABILITY_SELECTORS_ELEMENT);
attribute(COLLECTION_SIZE_ATTRIBUTE, selectors.length);
for (int j = 0; j < selectors.length; j++) {
writeTrimmedCdata(CAPABILITY_SELECTOR_ELEMENT, selectors[j]);
}
end(CAPABILITY_SELECTORS_ELEMENT);
}
end(REQUIRED_CAPABILITY_ELEMENT);
}
private void writeArtifactKeys(IArtifactKey[] artifactKeys) {
if (artifactKeys != null && artifactKeys.length > 0) {
start(ARTIFACT_KEYS_ELEMENT);
attribute(COLLECTION_SIZE_ATTRIBUTE, artifactKeys.length);
for (int i = 0; i < artifactKeys.length; i++) {
start(ARTIFACT_KEY_ELEMENT);
attribute(ARTIFACT_KEY_NAMESPACE_ATTRIBUTE, artifactKeys[i].getNamespace());
attribute(ARTIFACT_KEY_CLASSIFIER_ATTRIBUTE, artifactKeys[i].getClassifier());
attribute(ID_ATTRIBUTE, artifactKeys[i].getId());
attribute(VERSION_ATTRIBUTE, artifactKeys[i].getVersion());
end(ARTIFACT_KEY_ELEMENT);
}
end(ARTIFACT_KEYS_ELEMENT);
}
}
private void writeTouchpointType(TouchpointType touchpointType) {
start(TOUCHPOINT_TYPE_ELEMENT);
attribute(ID_ATTRIBUTE, touchpointType.getId());
attribute(VERSION_ATTRIBUTE, touchpointType.getVersion());
end(TOUCHPOINT_TYPE_ELEMENT);
}
private void writeTouchpointData(TouchpointData[] touchpointData) {
if (touchpointData != null && touchpointData.length > 0) {
start(TOUCHPOINT_DATA_ELEMENT);
attribute(COLLECTION_SIZE_ATTRIBUTE, touchpointData.length);
for (int i = 0; i < touchpointData.length; i++) {
TouchpointData nextData = touchpointData[i];
Map instructions = nextData.getInstructions();
if (instructions.size() > 0) {
start(TOUCHPOINT_DATA_INSTRUCTIONS_ELEMENT);
attribute(COLLECTION_SIZE_ATTRIBUTE, instructions.size());
for (Iterator iter = instructions.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
start(TOUCHPOINT_DATA_INSTRUCTION_ELEMENT);
attribute(TOUCHPOINT_DATA_INSTRUCTION_KEY_ATTRIBUTE, entry.getKey());
cdata((String) entry.getValue(), true);
end(TOUCHPOINT_DATA_INSTRUCTION_ELEMENT);
}
}
}
end(TOUCHPOINT_DATA_ELEMENT);
}
}
private void writeTrimmedCdata(String element, String filter) {
String trimmed;
if (filter != null && (trimmed = filter.trim()).length() > 0) {
start(element);
cdata(trimmed);
end(element);
}
}
}
/*
* Parser for the contents of an InstallRegistry,
* as written by the Writer class.
*/
private class Parser extends XMLParser implements XMLConstants {
private Map profileInstallRegistries = null;
public Parser(BundleContext context, String bundleId) {
super(context, bundleId);
}
public void parse(File file) throws IOException {
parse(new FileInputStream(file));
}
public synchronized void parse(InputStream stream) throws IOException {
this.status = null;
try {
// TODO: currently not caching the parser since we make no assumptions
// or restrictions on concurrent parsing
getParser();
InstallRegistryHandler registryHandler = new InstallRegistryHandler();
xmlReader.setContentHandler(new InstallRegistryDocHandler(INSTALL_REGISTRY_ELEMENT, registryHandler));
xmlReader.parse(new InputSource(stream));
if (this.isValidXML()) {
profileInstallRegistries = registryHandler.getProfileInstallRegistries();
}
} catch (SAXException e) {
throw new IOException(e.getMessage());
} catch (ParserConfigurationException e) {
throw new IOException(e.getMessage());
} finally {
stream.close();
}
}
public Map getProfileInstallRegistries() {
return profileInstallRegistries;
}
protected Object getRootObject() {
return profileInstallRegistries;
}
private final class InstallRegistryDocHandler extends DocHandler {
public InstallRegistryDocHandler(String rootName, RootHandler rootHandler) {
super(rootName, rootHandler);
}
public void ProcessingInstruction(String target, String data) throws SAXException {
if (PI_REPOSITORY_TARGET.equalsIgnoreCase(target)) {
// TODO: should the root handler be constructed based on class
// via an extension registry mechanism?
// String clazz = extractPIClass(data);
// and
// TODO: version tolerance by extension
Version repositoryVersion = extractPIVersion(target, data);
if (!XML_TOLERANCE.isIncluded(repositoryVersion)) {
throw new SAXException(NLS.bind(Messages.InstallRegistry_Parser_Has_Incompatible_Version, repositoryVersion, XML_TOLERANCE));
}
}
}
}
private final class InstallRegistryHandler extends RootHandler {
private ProfileInstallRegistriesHandler profilesHandler = null;
private Map profyleRegistries = null;
public InstallRegistryHandler() {
super();
}
protected void handleRootAttributes(Attributes attributes) {
parseRequiredAttributes(attributes, noAttributes);
}
public void startElement(String name, Attributes attributes) {
if (PROFILE_INSTALL_REGISTRIES_ELEMENT.equalsIgnoreCase(name)) {
if (profilesHandler == null) {
profilesHandler = new ProfileInstallRegistriesHandler(this, attributes);
} else {
duplicateElement(this, name, attributes);
}
} else {
invalidElement(name, attributes);
}
}
public Map getProfileInstallRegistries() {
return (profyleRegistries != null ? profyleRegistries : new LinkedHashMap(0));
}
protected void finished() {
if (isValidXML()) {
ProfileInstallRegistry[] registries = (profilesHandler == null ? new ProfileInstallRegistry[0] //
: profilesHandler.getProfileInstallRegistries());
profyleRegistries = new LinkedHashMap(registries.length);
for (int i = 0; i < registries.length; i++) {
ProfileInstallRegistry nextProfileRegistry = registries[i];
profyleRegistries.put(nextProfileRegistry.getProfileId(), nextProfileRegistry);
}
}
}
}
protected class ProfileInstallRegistriesHandler extends AbstractHandler {
private List profileRegistries = null;
public ProfileInstallRegistriesHandler(AbstractHandler parentHandler, Attributes attributes) {
super(parentHandler, PROFILE_INSTALL_REGISTRIES_ELEMENT);
String size = parseOptionalAttribute(attributes, COLLECTION_SIZE_ATTRIBUTE);
profileRegistries = (size != null ? new ArrayList(new Integer(size).intValue()) : new ArrayList(4));
}
public void startElement(String name, Attributes attributes) {
if (name.equalsIgnoreCase(PROFILE_INSTALL_REGISTRY_ELEMENT)) {
new ProfileInstallRegistryHandler(this, attributes, profileRegistries);
} else {
invalidElement(name, attributes);
}
}
public ProfileInstallRegistry[] getProfileInstallRegistries() {
return (ProfileInstallRegistry[]) profileRegistries.toArray(new ProfileInstallRegistry[profileRegistries.size()]);
}
}
protected class ProfileInstallRegistryHandler extends AbstractHandler {
private final String[] required = new String[] {PROFILE_ID_ATTRIBUTE};
List registries = null;
private String profileId = null;
private InstallableUnitsHandler unitsHandler = null;
private IUsPropertiesHandler iusPropertiesHandler = null;
public ProfileInstallRegistryHandler(AbstractHandler parentHandler, Attributes attributes, List registries) {
super(parentHandler, PROFILE_INSTALL_REGISTRY_ELEMENT);
profileId = parseRequiredAttributes(attributes, required)[0];
this.registries = registries;
}
public void startElement(String name, Attributes attributes) {
if (INSTALLABLE_UNITS_ELEMENT.equalsIgnoreCase(name)) {
if (unitsHandler == null) {
unitsHandler = new InstallableUnitsHandler(this, attributes);
} else {
duplicateElement(this, name, attributes);
}
} else if (IUS_PROPERTIES_ELEMENT.equalsIgnoreCase(name)) {
if (iusPropertiesHandler == null) {
iusPropertiesHandler = new IUsPropertiesHandler(this, attributes);
} else {
duplicateElement(this, name, attributes);
}
} else {
invalidElement(name, attributes);
}
}
protected void finished() {
if (isValidXML() && profileId != null) {
IInstallableUnit[] units = (unitsHandler == null ? new IInstallableUnit[0] //
: unitsHandler.getUnits());
Map iusPropertiesMap = (iusPropertiesHandler == null ? new LinkedHashMap() //
: iusPropertiesHandler.getIUsPropertiesMap());
ProfileInstallRegistry registry = new ProfileInstallRegistry(profileId, units, iusPropertiesMap);
registries.add(registry);
}
}
}
protected class IUsPropertiesHandler extends AbstractHandler {
private Map iusPropertiesMap;
public IUsPropertiesHandler(AbstractHandler parentHandler, Attributes attributes) {
super(parentHandler, IUS_PROPERTIES_ELEMENT);
String size = parseOptionalAttribute(attributes, COLLECTION_SIZE_ATTRIBUTE);
iusPropertiesMap = (size != null ? new LinkedHashMap(new Integer(size).intValue()) : new LinkedHashMap(4));
}
public Map getIUsPropertiesMap() {
return iusPropertiesMap;
}
public void startElement(String name, Attributes attributes) {
if (name.equalsIgnoreCase(IU_PROPERTIES_ELEMENT)) {
new IUPropertiesHandler(this, attributes, iusPropertiesMap);
} else {
invalidElement(name, attributes);
}
}
}
protected class IUPropertiesHandler extends AbstractHandler {
private final String[] required = new String[] {ID_ATTRIBUTE, VERSION_ATTRIBUTE};
private IUIdentity iuIdentity = null;
private PropertiesHandler propertiesHandler = null;
private Map iusPropertiesMap = null;
public IUPropertiesHandler(AbstractHandler parentHandler, Attributes attributes, Map iusPropertiesMap) {
super(parentHandler, IU_PROPERTIES_ELEMENT);
String values[] = parseRequiredAttributes(attributes, required);
Version version = checkVersion(IU_PROPERTIES_ELEMENT, VERSION_ATTRIBUTE, values[1]);
iuIdentity = new IUIdentity(values[0], version);
this.iusPropertiesMap = iusPropertiesMap;
}
public void startElement(String name, Attributes attributes) {
if (name.equalsIgnoreCase(PROPERTIES_ELEMENT)) {
propertiesHandler = new PropertiesHandler(this, attributes);
} else {
invalidElement(name, attributes);
}
}
protected void finished() {
if (isValidXML() && iuIdentity != null && propertiesHandler != null) {
iusPropertiesMap.put(iuIdentity, propertiesHandler.getProperties());
}
}
}
// TODO: below is a LOT of code duplicated for MetadataRepositoryIO for writing
// installable units. Need to figure out a cleanway to declare handlers
// which do not depend on the context of an outer declaring Parser class,
// so that handlers may be reused in different parsing contexts.
protected class InstallableUnitsHandler extends AbstractHandler {
private ArrayList units;
public InstallableUnitsHandler(AbstractHandler parentHandler, Attributes attributes) {
super(parentHandler, INSTALLABLE_UNITS_ELEMENT);
String size = parseOptionalAttribute(attributes, COLLECTION_SIZE_ATTRIBUTE);
units = (size != null ? new ArrayList(new Integer(size).intValue()) : new ArrayList(4));
}
public IInstallableUnit[] getUnits() {
return (IInstallableUnit[]) units.toArray(new IInstallableUnit[units.size()]);
}
public void startElement(String name, Attributes attributes) {
if (name.equalsIgnoreCase(INSTALLABLE_UNIT_ELEMENT)) {
new InstallableUnitHandler(this, attributes, units);
} else {
invalidElement(name, attributes);
}
}
}
protected class InstallableUnitHandler extends AbstractHandler {
private final String[] required = new String[] {ID_ATTRIBUTE, VERSION_ATTRIBUTE};
private final String[] optional = new String[] {SINGLETON_ATTRIBUTE, FRAGMENT_ATTRIBUTE, FRAGMENT_HOST_ID_ATTRIBUTE, FRAGMENT_HOST_RANGE_ATTRIBUTE};
InstallableUnit currentUnit = null;
private PropertiesHandler propertiesHandler = null;
private ProvidedCapabilitiesHandler providedCapabilitiesHandler = null;
private RequiredCapabilitiesHandler requiredCapabilitiesHandler = null;
private TextHandler filterHandler = null;
private TextHandler applicabilityHandler = null;
private ArtifactsHandler artifactsHandler = null;
private TouchpointTypeHandler touchpointTypeHandler = null;
private TouchpointDataHandler touchpointDataHandler = null;
public InstallableUnitHandler(AbstractHandler parentHandler, Attributes attributes, List units) {
super(parentHandler, INSTALLABLE_UNIT_ELEMENT);
String[] values = parseAttributes(attributes, required, optional);
Version version = checkVersion(INSTALLABLE_UNIT_ELEMENT, VERSION_ATTRIBUTE, values[1]);
boolean singleton = checkBoolean(INSTALLABLE_UNIT_ELEMENT, SINGLETON_ATTRIBUTE, values[2], true).booleanValue();
boolean isFragment = checkBoolean(INSTALLABLE_UNIT_ELEMENT, FRAGMENT_ATTRIBUTE, values[3], false).booleanValue();
if (isFragment) {
// TODO: tooling default fragment does not have a host id
// checkRequiredAttribute(INSTALLABLE_UNIT_ELEMENT, FRAGMENT_HOST_ID_ATTRIBUTE, values[4]);
checkRequiredAttribute(INSTALLABLE_UNIT_ELEMENT, FRAGMENT_HOST_RANGE_ATTRIBUTE, values[5]);
VersionRange hostRange = checkVersionRange(INSTALLABLE_UNIT_ELEMENT, FRAGMENT_HOST_RANGE_ATTRIBUTE, values[5]);
currentUnit = new InstallableUnitFragment(values[0], version, singleton, values[4], hostRange);
} else {
if (values[4] != null) {
unexpectedAttribute(INSTALLABLE_UNIT_ELEMENT, FRAGMENT_HOST_ID_ATTRIBUTE, values[4]);
} else if (values[5] != null) {
unexpectedAttribute(INSTALLABLE_UNIT_ELEMENT, FRAGMENT_HOST_RANGE_ATTRIBUTE, values[4]);
}
currentUnit = new InstallableUnit(values[0], version, singleton);
}
units.add(currentUnit);
}
public IInstallableUnit getInstallableUnit() {
return currentUnit;
}
public void startElement(String name, Attributes attributes) {
if (PROPERTIES_ELEMENT.equalsIgnoreCase(name)) {
if (propertiesHandler == null) {
propertiesHandler = new PropertiesHandler(this, attributes);
} else {
duplicateElement(this, name, attributes);
}
} else if (PROVIDED_CAPABILITIES_ELEMENT.equalsIgnoreCase(name)) {
if (providedCapabilitiesHandler == null) {
providedCapabilitiesHandler = new ProvidedCapabilitiesHandler(this, attributes);
} else {
duplicateElement(this, name, attributes);
}
} else if (REQUIRED_CAPABILITIES_ELEMENT.equalsIgnoreCase(name)) {
if (requiredCapabilitiesHandler == null) {
requiredCapabilitiesHandler = new RequiredCapabilitiesHandler(this, attributes);
} else {
duplicateElement(this, name, attributes);
}
} else if (IU_FILTER_ELEMENT.equalsIgnoreCase(name)) {
if (filterHandler == null) {
filterHandler = new TextHandler(this, IU_FILTER_ELEMENT, attributes);
} else {
duplicateElement(this, name, attributes);
}
} else if (APPLICABILITY_FILTER_ELEMENT.equalsIgnoreCase(name)) {
if (applicabilityHandler == null) {
applicabilityHandler = new TextHandler(this, APPLICABILITY_FILTER_ELEMENT, attributes);
} else {
duplicateElement(this, name, attributes);
}
} else if (ARTIFACT_KEYS_ELEMENT.equalsIgnoreCase(name)) {
if (artifactsHandler == null) {
artifactsHandler = new ArtifactsHandler(this, attributes);
} else {
duplicateElement(this, name, attributes);
}
} else if (TOUCHPOINT_TYPE_ELEMENT.equalsIgnoreCase(name)) {
if (touchpointTypeHandler == null) {
touchpointTypeHandler = new TouchpointTypeHandler(this, attributes);
} else {
duplicateElement(this, name, attributes);
}
} else if (TOUCHPOINT_DATA_ELEMENT.equalsIgnoreCase(name)) {
if (touchpointDataHandler == null) {
touchpointDataHandler = new TouchpointDataHandler(this, attributes);
} else {
duplicateElement(this, name, attributes);
}
} else {
invalidElement(name, attributes);
}
}
protected void finished() {
if (isValidXML() && currentUnit != null) {
OrderedProperties properties = (propertiesHandler == null ? new OrderedProperties(0) //
: propertiesHandler.getProperties());
currentUnit.addProperties(properties);
ProvidedCapability[] providedCapabilities = (providedCapabilitiesHandler == null ? new ProvidedCapability[0] //
: providedCapabilitiesHandler.getProvidedCapabilities());
currentUnit.setCapabilities(providedCapabilities);
RequiredCapability[] requiredCapabilities = (requiredCapabilitiesHandler == null ? new RequiredCapability[0] //
: requiredCapabilitiesHandler.getRequiredCapabilities());
currentUnit.setRequiredCapabilities(requiredCapabilities);
if (filterHandler != null) {
currentUnit.setFilter(filterHandler.getText());
}
if (applicabilityHandler != null) {
currentUnit.setApplicabilityFilter(applicabilityHandler.getText());
}
IArtifactKey[] artifacts = (artifactsHandler == null ? new IArtifactKey[0] //
: artifactsHandler.getArtifactKeys());
currentUnit.setArtifacts(artifacts);
if (touchpointTypeHandler != null) {
currentUnit.setTouchpointType(touchpointTypeHandler.getTouchpointType());
} else {
// TODO: create an error
}
TouchpointData[] touchpointData = (touchpointDataHandler == null ? new TouchpointData[0] //
: touchpointDataHandler.getTouchpointData());
currentUnit.addTouchpointData(touchpointData);
}
}
}
protected class ProvidedCapabilitiesHandler extends AbstractHandler {
private List providedCapabilities;
public ProvidedCapabilitiesHandler(AbstractHandler parentHandler, Attributes attributes) {
super(parentHandler, PROVIDED_CAPABILITIES_ELEMENT);
String size = parseOptionalAttribute(attributes, COLLECTION_SIZE_ATTRIBUTE);
providedCapabilities = (size != null ? new ArrayList(new Integer(size).intValue()) : new ArrayList(4));
}
public ProvidedCapability[] getProvidedCapabilities() {
return (ProvidedCapability[]) providedCapabilities.toArray(new ProvidedCapability[providedCapabilities.size()]);
}
public void startElement(String name, Attributes attributes) {
if (name.equalsIgnoreCase(PROVIDED_CAPABILITY_ELEMENT)) {
new ProvidedCapabilityHandler(this, attributes, providedCapabilities);
} else {
invalidElement(name, attributes);
}
}
}
protected class ProvidedCapabilityHandler extends AbstractHandler {
private final String[] required = new String[] {NAMESPACE_ATTRIBUTE, NAME_ATTRIBUTE, VERSION_ATTRIBUTE};
public ProvidedCapabilityHandler(AbstractHandler parentHandler, Attributes attributes, List capabilities) {
super(parentHandler, PROVIDED_CAPABILITY_ELEMENT);
String[] values = parseRequiredAttributes(attributes, required);
Version version = checkVersion(PROVIDED_CAPABILITY_ELEMENT, VERSION_ATTRIBUTE, values[2]);
capabilities.add(new ProvidedCapability(values[0], values[1], version));
}
public void startElement(String name, Attributes attributes) {
invalidElement(name, attributes);
}
}
protected class RequiredCapabilitiesHandler extends AbstractHandler {
private List requiredCapabilities;
public RequiredCapabilitiesHandler(AbstractHandler parentHandler, Attributes attributes) {
super(parentHandler, REQUIRED_CAPABILITIES_ELEMENT);
String size = parseOptionalAttribute(attributes, COLLECTION_SIZE_ATTRIBUTE);
requiredCapabilities = (size != null ? new ArrayList(new Integer(size).intValue()) : new ArrayList(4));
}
public RequiredCapability[] getRequiredCapabilities() {
return (RequiredCapability[]) requiredCapabilities.toArray(new RequiredCapability[requiredCapabilities.size()]);
}
public void startElement(String name, Attributes attributes) {
if (name.equalsIgnoreCase(REQUIRED_CAPABILITY_ELEMENT)) {
new RequiredCapabilityHandler(this, attributes, requiredCapabilities);
} else {
invalidElement(name, attributes);
}
}
}
protected class RequiredCapabilityHandler extends AbstractHandler {
private final String[] required = new String[] {NAMESPACE_ATTRIBUTE, NAME_ATTRIBUTE, VERSION_RANGE_ATTRIBUTE};
private final String[] optional = new String[] {CAPABILITY_OPTIONAL_ATTRIBUTE, CAPABILITY_MULTIPLE_ATTRIBUTE};
private RequiredCapability currentCapability = null;
private TextHandler filterHandler = null;
private CapabilitySelectorsHandler selectorsHandler = null;
public RequiredCapabilityHandler(AbstractHandler parentHandler, Attributes attributes, List capabilities) {
super(parentHandler, REQUIRED_CAPABILITY_ELEMENT);
String[] values = parseAttributes(attributes, required, optional);
VersionRange range = checkVersionRange(REQUIRED_CAPABILITY_ELEMENT, VERSION_RANGE_ATTRIBUTE, values[2]);
boolean isOptional = checkBoolean(REQUIRED_CAPABILITY_ELEMENT, CAPABILITY_OPTIONAL_ATTRIBUTE, values[3], false).booleanValue();
boolean isMultiple = checkBoolean(REQUIRED_CAPABILITY_ELEMENT, CAPABILITY_MULTIPLE_ATTRIBUTE, values[4], false).booleanValue();
currentCapability = new RequiredCapability(values[0], values[1], range, null, isOptional, isMultiple);
capabilities.add(currentCapability);
}
public void startElement(String name, Attributes attributes) {
if (name.equalsIgnoreCase(CAPABILITY_FILTER_ELEMENT)) {
filterHandler = new TextHandler(this, CAPABILITY_FILTER_ELEMENT, attributes);
} else if (name.equalsIgnoreCase(CAPABILITY_SELECTORS_ELEMENT)) {
selectorsHandler = new CapabilitySelectorsHandler(this, attributes);
} else {
invalidElement(name, attributes);
}
}
protected void finished() {
if (isValidXML()) {
if (currentCapability != null) {
if (filterHandler != null) {
currentCapability.setFilter(filterHandler.getText());
}
if (selectorsHandler != null) {
currentCapability.setSelectors(selectorsHandler.getSelectors());
}
}
}
}
}
protected class ArtifactsHandler extends AbstractHandler {
private List artifacts;
public ArtifactsHandler(AbstractHandler parentHandler, Attributes attributes) {
super(parentHandler, ARTIFACT_KEYS_ELEMENT);
String size = parseOptionalAttribute(attributes, COLLECTION_SIZE_ATTRIBUTE);
artifacts = (size != null ? new ArrayList(new Integer(size).intValue()) : new ArrayList(4));
}
public IArtifactKey[] getArtifactKeys() {
return (IArtifactKey[]) artifacts.toArray(new IArtifactKey[artifacts.size()]);
}
public void startElement(String name, Attributes attributes) {
if (name.equalsIgnoreCase(ARTIFACT_KEY_ELEMENT)) {
new ArtifactHandler(this, attributes, artifacts);
} else {
invalidElement(name, attributes);
}
}
}
protected class ArtifactHandler extends AbstractHandler {
private final String[] required = new String[] {NAMESPACE_ATTRIBUTE, CLASSIFIER_ATTRIBUTE, ID_ATTRIBUTE, VERSION_ATTRIBUTE};
public ArtifactHandler(AbstractHandler parentHandler, Attributes attributes, List artifacts) {
super(parentHandler, ARTIFACT_KEY_ELEMENT);
String[] values = parseRequiredAttributes(attributes, required);
Version version = checkVersion(ARTIFACT_KEY_ELEMENT, VERSION_ATTRIBUTE, values[3]);
artifacts.add(new ArtifactKey(values[0], values[1], values[2], version));
}
public void startElement(String name, Attributes attributes) {
invalidElement(name, attributes);
}
}
protected class CapabilitySelectorsHandler extends AbstractHandler {
private List selectors;
public CapabilitySelectorsHandler(AbstractHandler parentHandler, Attributes attributes) {
super(parentHandler, CAPABILITY_SELECTORS_ELEMENT);
String size = parseOptionalAttribute(attributes, COLLECTION_SIZE_ATTRIBUTE);
selectors = (size != null ? new ArrayList(new Integer(size).intValue()) : new ArrayList(4));
}
public String[] getSelectors() {
return (String[]) selectors.toArray(new String[selectors.size()]);
}
public void startElement(String name, Attributes attributes) {
if (name.equalsIgnoreCase(CAPABILITY_SELECTOR_ELEMENT)) {
new TextHandler(this, CAPABILITY_SELECTOR_ELEMENT, attributes, selectors);
} else {
invalidElement(name, attributes);
}
}
}
protected class TouchpointTypeHandler extends AbstractHandler {
private final String[] required = new String[] {ID_ATTRIBUTE, VERSION_ATTRIBUTE};
TouchpointType touchpointType = null;
public TouchpointTypeHandler(AbstractHandler parentHandler, Attributes attributes) {
super(parentHandler, TOUCHPOINT_TYPE_ELEMENT);
String[] values = parseRequiredAttributes(attributes, required);
Version version = checkVersion(TOUCHPOINT_TYPE_ELEMENT, VERSION_ATTRIBUTE, values[1]);
touchpointType = new TouchpointType(values[0], version);
}
public TouchpointType getTouchpointType() {
return touchpointType;
}
public void startElement(String name, Attributes attributes) {
invalidElement(name, attributes);
}
}
protected class TouchpointDataHandler extends AbstractHandler {
TouchpointData touchpointData = null;
List data = null;
public TouchpointDataHandler(AbstractHandler parentHandler, Attributes attributes) {
super(parentHandler, TOUCHPOINT_DATA_ELEMENT);
String size = parseOptionalAttribute(attributes, COLLECTION_SIZE_ATTRIBUTE);
data = (size != null ? new ArrayList(new Integer(size).intValue()) : new ArrayList(4));
}
public TouchpointData[] getTouchpointData() {
return (TouchpointData[]) data.toArray(new TouchpointData[data.size()]);
}
public void startElement(String name, Attributes attributes) {
if (name.equalsIgnoreCase(TOUCHPOINT_DATA_INSTRUCTIONS_ELEMENT)) {
new TouchpointInstructionsHandler(this, attributes, data);
} else {
invalidElement(name, attributes);
}
}
}
protected class TouchpointInstructionsHandler extends AbstractHandler {
Map instructions = null;
public TouchpointInstructionsHandler(AbstractHandler parentHandler, Attributes attributes, List data) {
super(parentHandler, TOUCHPOINT_DATA_INSTRUCTIONS_ELEMENT);
String size = parseOptionalAttribute(attributes, COLLECTION_SIZE_ATTRIBUTE);
instructions = (size != null ? new LinkedHashMap(new Integer(size).intValue()) : new LinkedHashMap(4));
data.add(new TouchpointData(instructions));
}
public void startElement(String name, Attributes attributes) {
if (name.equalsIgnoreCase(TOUCHPOINT_DATA_INSTRUCTION_ELEMENT)) {
new TouchpointInstructionHandler(this, attributes, instructions);
} else {
invalidElement(name, attributes);
}
}
}
protected class TouchpointInstructionHandler extends TextHandler {
private final String[] required = new String[] {TOUCHPOINT_DATA_INSTRUCTION_KEY_ATTRIBUTE};
Map instructions = null;
String key = null;
public TouchpointInstructionHandler(AbstractHandler parentHandler, Attributes attributes, Map instructions) {
super(parentHandler, TOUCHPOINT_DATA_INSTRUCTION_ELEMENT);
key = parseRequiredAttributes(attributes, required)[0];
this.instructions = instructions;
}
protected void finished() {
if (isValidXML()) {
if (key != null) {
instructions.put(key, getText());
}
}
}
}
protected String getErrorMessage() {
return Messages.InstallRegistry_Parser_Error_Parsing_Registry;
}
public String toString() {
// TODO:
return null;
}
}
}