blob: 1cb3465fe9a7aeaa06e2c1d3f8b06483b69060d5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 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.dltk.internal.core;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.Path;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IAccessRule;
import org.eclipse.dltk.core.IBuildpathAttribute;
import org.eclipse.dltk.core.IBuildpathEntry;
import org.eclipse.dltk.internal.core.util.Messages;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* Internal model element to represent a user library and code to serialize /
* deserialize.
*/
public class UserLibrary {
private static final String CURRENT_VERSION = "1"; //$NON-NLS-1$
private static final String TAG_VERSION = "version"; //$NON-NLS-1$
private static final String TAG_USERLIBRARY = "userlibrary"; //$NON-NLS-1$
private static final String TAG_PATH = "path"; //$NON-NLS-1$
private static final String TAG_ARCHIVE = "archive"; //$NON-NLS-1$
private static final String TAG_SYSTEMLIBRARY = "systemlibrary"; //$NON-NLS-1$
private static final String ATTRIBUTE_PREFIX = "__attribute__"; //$NON-NLS-1$
private boolean isSystemLibrary;
private IBuildpathEntry[] entries;
private Map<String, String> attributes;
public UserLibrary(IBuildpathEntry[] entries, boolean isSystemLibrary) {
this(entries, isSystemLibrary, null);
}
public UserLibrary(IBuildpathEntry[] entries, boolean isSystemLibrary,
Map<String, String> attributes) {
Assert.isNotNull(entries);
this.entries = entries;
this.isSystemLibrary = isSystemLibrary;
this.attributes = new HashMap<String, String>();
if (attributes != null) {
this.attributes.putAll(attributes);
}
}
public IBuildpathEntry[] getEntries() {
return this.entries;
}
public boolean isSystemLibrary() {
return this.isSystemLibrary;
}
public String getAttribute(String name) {
return attributes.get(name);
}
public Map<String, String> getAttributes() {
return attributes;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
if (obj != null && obj.getClass() == getClass()) {
UserLibrary other = (UserLibrary) obj;
if (this.entries.length == other.entries.length
&& this.isSystemLibrary == other.isSystemLibrary
&& attributes.size() == other.attributes.size()) {
if (!Arrays.equals(this.entries, other.entries)) {
return false;
}
if (!this.attributes.equals(other.attributes)) {
return false;
}
return true;
}
}
return false;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
int hashCode = 0;
if (this.isSystemLibrary()) {
hashCode++;
}
for (int i = 0; i < this.entries.length; i++) {
hashCode = hashCode * 17 + this.entries[i].hashCode();
}
return hashCode;
}
public static String serialize(IBuildpathEntry[] entries,
boolean isSystemLibrary) throws IOException {
return serialize(entries, isSystemLibrary, null);
}
public static String serialize(IBuildpathEntry[] entries,
boolean isSystemLibrary, Map<String, String> attributes)
throws IOException {
ByteArrayOutputStream s = new ByteArrayOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
XMLWriter xmlWriter = new XMLWriter(writer, null/*
* use the workspace
* line delimiter
*/, true/*
* print XML
* version
*/);
HashMap<String, String> library = new HashMap<String, String>();
library.put(TAG_VERSION, String.valueOf(CURRENT_VERSION));
library.put(TAG_SYSTEMLIBRARY, String.valueOf(isSystemLibrary));
if (attributes != null) {
for (String key : attributes.keySet()) {
library.put(ATTRIBUTE_PREFIX + key, attributes.get(key));
}
}
xmlWriter.printTag(TAG_USERLIBRARY, library, true, true, false);
for (int i = 0, length = entries.length; i < length; ++i) {
BuildpathEntry cpEntry = (BuildpathEntry) entries[i];
HashMap<String, String> archive = new HashMap<String, String>();
archive.put(TAG_PATH, cpEntry.getPath().toString());
boolean hasExtraAttributes = cpEntry.extraAttributes != null
&& cpEntry.extraAttributes.length != 0;
boolean hasRestrictions = cpEntry.getAccessRuleSet() != null; // access
// rule
// set
// is
// null
// if
// no
// access
// rules
xmlWriter.printTag(TAG_ARCHIVE, archive, true, true,
!(hasExtraAttributes || hasRestrictions));
// write extra attributes if necessary
if (hasExtraAttributes) {
cpEntry.encodeExtraAttributes(xmlWriter, true, true);
}
// write extra attributes and restriction if necessary
if (hasRestrictions) {
cpEntry.encodeAccessRules(xmlWriter, true, true);
}
// write archive end tag if necessary
if (hasExtraAttributes || hasRestrictions) {
xmlWriter.endTag(TAG_ARCHIVE, true/* insert tab */, true/*
* insert
* new line
*/);
}
}
xmlWriter.endTag(TAG_USERLIBRARY, true/* insert tab */, true/*
* insert new
* line
*/);
writer.flush();
writer.close();
return s.toString("UTF8");//$NON-NLS-1$
}
public static UserLibrary createFromString(Reader reader)
throws IOException {
Element cpElement;
try {
DocumentBuilder parser = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
cpElement = parser.parse(new InputSource(reader))
.getDocumentElement();
} catch (SAXException e) {
throw new IOException(Messages.file_badFormat);
} catch (ParserConfigurationException e) {
throw new IOException(Messages.file_badFormat);
} finally {
reader.close();
}
if (!cpElement.getNodeName().equalsIgnoreCase(TAG_USERLIBRARY)) {
throw new IOException(Messages.file_badFormat);
}
// String version= cpElement.getAttribute(TAG_VERSION);
// in case we update the format: add code to read older versions
boolean isSystem = Boolean.valueOf(
cpElement.getAttribute(TAG_SYSTEMLIBRARY)).booleanValue();
Map<String, String> attributes = new HashMap<String, String>();
for (int i = 0; i < cpElement.getAttributes().getLength(); i++) {
Node node = cpElement.getAttributes().item(i);
if (node.getNodeName().startsWith(ATTRIBUTE_PREFIX)) {
String name = node.getNodeName().substring(
ATTRIBUTE_PREFIX.length());
attributes.put(name, node.getNodeValue());
}
}
NodeList list = cpElement.getChildNodes();
int length = list.getLength();
ArrayList<IBuildpathEntry> res = new ArrayList<IBuildpathEntry>(length);
for (int i = 0; i < length; ++i) {
Node node = list.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
if (element.getNodeName().equals(TAG_ARCHIVE)) {
String path = element.getAttribute(TAG_PATH);
NodeList children = element.getElementsByTagName("*"); //$NON-NLS-1$
boolean[] foundChildren = new boolean[children.getLength()];
NodeList attributeList = BuildpathEntry.getChildAttributes(
BuildpathEntry.TAG_ATTRIBUTES, children,
foundChildren);
IBuildpathAttribute[] extraAttributes = BuildpathEntry
.decodeExtraAttributes(attributeList);
attributeList = BuildpathEntry.getChildAttributes(
BuildpathEntry.TAG_ACCESS_RULES, children,
foundChildren);
IAccessRule[] accessRules = BuildpathEntry
.decodeAccessRules(attributeList);
IBuildpathEntry entry = DLTKCore.newLibraryEntry(
Path.fromPortableString(path), accessRules,
extraAttributes, false, true);
res.add(entry);
}
}
}
IBuildpathEntry[] entries = res
.toArray(new IBuildpathEntry[res.size()]);
return new UserLibrary(entries, isSystem, attributes);
}
public String toString() {
if (this.entries == null)
return "null"; //$NON-NLS-1$
StringBuffer buffer = new StringBuffer();
int length = this.entries.length;
for (int i = 0; i < length; i++) {
buffer.append(this.entries[i].toString() + '\n');
}
return buffer.toString();
}
}