/*******************************************************************************
* Copyright (c) 2012, 2014 Wind River Systems, Inc. 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tcf.te.launch.core.persistence;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.tcf.te.launch.core.activator.CoreBundleActivator;
import org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchSpecification;
import org.eclipse.tcf.te.runtime.persistence.PersistenceManager;
import org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate;
/**
* Item list persistence delegate.
*/
public abstract class AbstractItemListPersistenceDelegate<ItemType> {
private final String tagName;
private final String key;
public AbstractItemListPersistenceDelegate(String tagName, String key) {
super();
Assert.isNotNull(tagName);
Assert.isNotNull(key);
this.tagName = tagName;
this.key = key;
}
/**
* Saves the selectedr items to the specified launch configuration working copy. If the
* selected items are <code>null</code> or empty, the attribute will be removed from
* the specified launch configuration working copy.
* @param <ItemType>
*
* @param wc The launch configuration working copy. Must not be <code>null</code>.
* @param items The items to save or <code>null</code>.
*/
public final void setItems(ILaunchConfigurationWorkingCopy wc, ItemType[] items) {
Assert.isNotNull(wc);
if (items == null || items.length == 0) {
DefaultPersistenceDelegate.setAttribute(wc, key, (String)null);
return;
}
// Get the encoded XML representation
String xml = encodeItems(items);
// And save them to the launch configuration. If XML == null, the
// items will be removed from the launch configuration
DefaultPersistenceDelegate.setAttribute(wc, key, xml);
}
/**
* Saves the selected items to the specified launch specification. If the selected
* items are <code>null</code> or empty, the attribute will be removed from the
* specified launch specification.
*
* @param launchSpec The launch specification. Must not be <code>null</code>.
* @param items The items to save or <code>null</code>.
*/
public final void setItems(ILaunchSpecification launchSpec, ItemType[] items) {
Assert.isNotNull(launchSpec);
if (items == null || items.length == 0) {
launchSpec.removeAttribute(key);
return;
}
// Get the encoded XML representation
String xml = encodeItems(items);
// And save them to the launch specification. If XML == null, the
// items will be removed from the launch specification
launchSpec.addAttribute(key, xml);
}
/**
* Writes the given items into a string encoded in XML.
*
* @param items The items to encode. Must not be <code>null</code>.
* @return The full XML representation of the given items or <code>null</code>.
*/
public final String encodeItems(ItemType[] items) {
Assert.isNotNull(items);
// The final result
String result = null;
// First, we write the selected items as XML representation into a string
StringWriter writer = new StringWriter();
try {
// Write the header and get the initial indentation
String indentation = writeHeader(writer);
// Iterate over the given selected items and write them out.
for (ItemType item : items) {
writeItem(writer, indentation, item);
}
// Write the footer
writeFooter(writer);
// Convert into a string
result = writer.toString();
}
catch (IOException e) {
// Export to the string writer failed --> remove attribute from launch configuration
if (Platform.inDebugMode()) {
IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(),
"Launch framework internal error: " + e.getLocalizedMessage(), e); //$NON-NLS-1$
Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status);
}
result = null;
}
finally {
try {
writer.close();
}
catch (IOException e) { /* ignored on purpose */
}
}
return result;
}
/**
* Writes the header to the given writer and returns the indentation to be used for following
* elements.
*
* @param writer The writer instance. Must not be <code>null</code>.
* @throws IOException in case the write failed.
*/
private String writeHeader(Writer writer) throws IOException {
Assert.isNotNull(writer);
writer.write("<" + tagName + "s>\n"); //$NON-NLS-1$ //$NON-NLS-2$
return "\t"; //$NON-NLS-1$
}
/**
* Writes the footer to the given writer and returns the indentation to be used for following
* elements.
*
* @param writer The writer instance. Must not be <code>null</code>.
* @throws IOException in case the write failed.
*/
private String writeFooter(Writer writer) throws IOException {
Assert.isNotNull(writer);
writer.write("</" + tagName + "s>\n"); //$NON-NLS-1$ //$NON-NLS-2$
return ""; //$NON-NLS-1$
}
/**
* Writes the item to the given writer.
*
* @param writer The writer instance. Must not be <code>null</code>.
* @param indentation The indentation to prefix each exported line with. Must not be <code>null</code>.
* @param item The item instance. Must not be <code>null</code>.
*
* @throws IOException in case the write failed.
*/
private void writeItem(Writer writer, String indentation, ItemType item) throws IOException {
Assert.isNotNull(writer);
Assert.isNotNull(indentation);
Assert.isNotNull(item);
IPersistenceDelegate delegate = PersistenceManager.getInstance().getDelegate(item, String.class);
if (delegate != null) {
writer.write(indentation + "<" + tagName + " " + AbstractItemListXMLParser.ATTR_TYPE + "=\"" + delegate.getPersistedClass(item).getName() + "\">\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
writer.write(indentation + "\t" + delegate.write(item, String.class) + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
writer.write(indentation + "</" + tagName + ">\n"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
/**
* Reads the selected items from the given XML encoded string.
*
* @param encodedItems The selected items encoded as XML string. Must not be <code>null</code>.
* @return The selected items or an empty array.
*/
public final List<ItemType> decodeItems(String encodedItems) {
Assert.isNotNull(encodedItems);
List<ItemType> items = new ArrayList<ItemType>();
if (!"".equals(encodedItems.trim())) { //$NON-NLS-1$
// We have to parse the items from the string
InputStream input = new ByteArrayInputStream(encodedItems.getBytes());
// Instantiate the XML parser
AbstractItemListXMLParser<ItemType> xmlParser = getXMLParser();
xmlParser.initXMLParser();
xmlParser.setItems(items);
try {
xmlParser.getXMLReader().parse(input, xmlParser);
}
catch (Exception e) {
// Import failed --> remove attribute from launch configuration
if (Platform.inDebugMode()) {
IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(),
"Launch framework internal error: " + e.getLocalizedMessage(), e); //$NON-NLS-1$
Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status);
}
items.clear();
}
}
return items;
}
protected abstract AbstractItemListXMLParser<ItemType> getXMLParser();
/**
* Returns the list of configured items from the given launch configuration.
* <p>
* If the given launch configuration is <code>null</code> and the method will return an empty
* array.
*
* @param configuration The launch configuration or <code>null</code>.
* @param ItemType
* @return The list of configured items or an empty array.
*/
public final List<ItemType> getItems(ILaunchConfiguration configuration) {
List<ItemType> items = new ArrayList<ItemType>();
if (configuration != null) {
// Read the attribute from the launch configuration
String encodedItems = DefaultPersistenceDelegate.getAttribute(configuration, key, (String) null);
if (encodedItems != null) {
items = decodeItems(encodedItems);
}
}
return items;
}
/**
* Returns the list of configured items from the given launch specification.
* <p>
* If the given launch specification is <code>null</code> and the method will return an empty
* array.
*
* @param launchSpec The launch specification or <code>null</code>.
* @return The list of configured items or an empty array.
*/
public final List<ItemType> getItems(ILaunchSpecification launchSpec) {
List<ItemType> items = new ArrayList<ItemType>();
if (launchSpec != null) {
// Read the attribute from the launch specification
String encodedItems = (String) launchSpec.getAttribute(key, null);
if (encodedItems != null) {
items = decodeItems(encodedItems);
}
}
return items;
}
}