| /********************************************************************** |
| * Copyright (c) 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM - Initial API and implementation |
| **********************************************************************/ |
| |
| package org.eclipse.wtp.releng.tools.component.api; |
| |
| import java.io.BufferedInputStream; |
| import java.io.ByteArrayInputStream; |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.UnsupportedEncodingException; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.StringTokenizer; |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.parsers.SAXParser; |
| import javax.xml.parsers.SAXParserFactory; |
| import javax.xml.transform.Transformer; |
| import javax.xml.transform.TransformerConfigurationException; |
| import javax.xml.transform.TransformerException; |
| import javax.xml.transform.TransformerFactory; |
| import javax.xml.transform.stream.StreamResult; |
| import javax.xml.transform.stream.StreamSource; |
| import org.eclipse.wtp.releng.tools.component.ILocation; |
| import org.xml.sax.Attributes; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.helpers.DefaultHandler; |
| |
| public class ComponentAPI |
| { |
| public static final String CONST_COMPONENT_API_XML = "component-api.xml"; |
| private static final String NS = "http://eclipse.org/wtp/releng/tools/component-api"; |
| private static final String ELEMENT_COMPONENT_API = "component-api"; |
| private static final String ELEMENT_INTERNAL_API = "internal-apis"; |
| private static final String ELEMENT_EXTERNAL_API = "external-apis"; |
| private static final String ELEMENT_PACKAGE_API = "package-api"; |
| private static final String ELEMENT_CLASS_API = "class-api"; |
| private static final String ELEMENT_METHOD_API = "method-api"; |
| private static final String ELEMENT_FIELD_API = "field-api"; |
| private static final String ATTR_XMLNS_API = "xmlns:api"; |
| private static final String ATTR_ACCESS = "access"; |
| private static final String ATTR_NAME = "name"; |
| private static final String ATTR_DESCRIPTOR = "descriptor"; |
| private static final String ATTR_REFERENCE = "reference"; |
| private static final String ATTR_IMPLEMENT = "implement"; |
| private static final String ATTR_SUBCLASS = "subclass"; |
| private static final String ATTR_INSTANTIATE = "instantiate"; |
| private static final String ATTR_THROWS = "throws"; |
| |
| protected ILocation location; |
| protected String name; |
| private APIs internalAPIs; |
| private APIs externalAPIs; |
| private boolean reload; |
| |
| public ComponentAPI() |
| { |
| internalAPIs = new APIs(); |
| externalAPIs = new APIs(); |
| reload = false; |
| } |
| |
| /** |
| * @return Returns the location. |
| */ |
| public ILocation getLocation() |
| { |
| return location; |
| } |
| |
| /** |
| * @param location The location to set. |
| */ |
| public void setLocation(ILocation location) |
| { |
| this.location = location; |
| reload = true; |
| } |
| |
| /** |
| * @return Returns the name. |
| */ |
| public String getName() |
| { |
| return name; |
| } |
| |
| /** |
| * @param name The name to set. |
| */ |
| public void setName(String name) |
| { |
| this.name = name; |
| } |
| |
| /** |
| * @return Returns the externalAPIs. |
| */ |
| public APIs getExternalAPIs() |
| { |
| return externalAPIs; |
| } |
| |
| /** |
| * @param externalAPIs The externalAPIs to set. |
| */ |
| public void setExternalAPIs(APIs externalAPIs) |
| { |
| this.externalAPIs = externalAPIs; |
| } |
| |
| /** |
| * @return Returns the internalAPIs. |
| */ |
| public APIs getInternalAPIs() |
| { |
| return internalAPIs; |
| } |
| |
| /** |
| * @param internalAPIs The internalAPIs to set. |
| */ |
| public void setInternalAPIs(APIs internalAPIs) |
| { |
| this.internalAPIs = internalAPIs; |
| } |
| |
| public void load() throws IOException, FileNotFoundException |
| { |
| if (reload) |
| { |
| try |
| { |
| SAXParserFactory factory = SAXParserFactory.newInstance(); |
| factory.setNamespaceAware(false); |
| factory.setValidating(false); |
| SAXParser parser = factory.newSAXParser(); |
| parser.parse(new InputSource(new BufferedInputStream(location.getInputStream())), new ComponentAPIHandler(this)); |
| } |
| catch (ParserConfigurationException pce) |
| { |
| pce.printStackTrace(); |
| } |
| catch (SAXException saxe) |
| { |
| saxe.printStackTrace(); |
| } |
| reload = false; |
| } |
| } |
| |
| public void saveAsHTML(ILocation html, String xsl) throws TransformerConfigurationException, TransformerException, IOException |
| { |
| TransformerFactory factory = TransformerFactory.newInstance(); |
| Transformer transformer = factory.newTransformer(new StreamSource(ClassLoader.getSystemResourceAsStream(xsl))); |
| transformer.transform(new StreamSource(new ByteArrayInputStream(getBytes())), new StreamResult(new FileOutputStream(new File(html.getAbsolutePath())))); |
| } |
| |
| public void save() throws IOException |
| { |
| if (location != null) |
| { |
| File file = new File(location.getAbsolutePath()); |
| file.getParentFile().mkdirs(); |
| FileOutputStream fos = new FileOutputStream(file); |
| fos.write(getBytes()); |
| fos.close(); |
| } |
| } |
| |
| private byte[] getBytes() throws UnsupportedEncodingException |
| { |
| StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); |
| sb.append("<api:component-api "); |
| saveAttribute(sb, ATTR_XMLNS_API, NS); |
| saveAttribute(sb, ATTR_NAME, getName()); |
| sb.append(">"); |
| saveInternalAPIs(sb, getInternalAPIs()); |
| saveExternalAPIs(sb, getExternalAPIs()); |
| sb.append("</api:component-api>"); |
| return sb.toString().getBytes("UTF-8"); |
| } |
| |
| private void saveInternalAPIs(StringBuffer sb, APIs apis) |
| { |
| List pkgAPIs = apis.getPackageAPIs(); |
| if (pkgAPIs.size() > 0) |
| { |
| sb.append("<internal-apis>"); |
| for (Iterator it = pkgAPIs.iterator(); it.hasNext();) |
| savePackageAPI(sb, (PackageAPI)it.next()); |
| sb.append("</internal-apis>"); |
| } |
| } |
| |
| private void saveExternalAPIs(StringBuffer sb, APIs apis) |
| { |
| List pkgAPIs = apis.getPackageAPIs(); |
| if (pkgAPIs.size() > 0) |
| { |
| sb.append("<external-apis>"); |
| for (Iterator it = pkgAPIs.iterator(); it.hasNext();) |
| savePackageAPI(sb, (PackageAPI)it.next()); |
| sb.append("</external-apis>"); |
| } |
| } |
| |
| private void savePackageAPI(StringBuffer sb, PackageAPI pkgAPI) |
| { |
| sb.append("<package-api"); |
| saveAttribute(sb, ATTR_NAME, pkgAPI.getName()); |
| sb.append(">"); |
| for (Iterator it = pkgAPI.getClassAPIs().iterator(); it.hasNext();) |
| sb.append(((ClassAPI)it.next()).toString()); |
| sb.append("</package-api>"); |
| } |
| |
| protected void saveAttribute(StringBuffer sb, String key, String value) |
| { |
| if (key != null && value != null) |
| { |
| sb.append(" "); |
| sb.append(key); |
| sb.append("=\""); |
| sb.append(value); |
| sb.append("\""); |
| } |
| } |
| |
| protected void saveAttribute(StringBuffer sb, String key, List values, String delimiter) |
| { |
| if (key != null && values != null && values.size() > 0) |
| { |
| sb.append(" "); |
| sb.append(key); |
| sb.append("=\""); |
| for (Iterator it = values.iterator(); it.hasNext();) |
| { |
| sb.append(it.next().toString()); |
| if (it.hasNext()) |
| sb.append(delimiter); |
| } |
| sb.append("\""); |
| } |
| } |
| |
| protected static class ComponentAPIHandler extends DefaultHandler |
| { |
| private ComponentAPI compAPI; |
| private APIs apis; |
| private PackageAPI packageAPI; |
| private ClassAPI classAPI; |
| |
| public ComponentAPIHandler(ComponentAPI compAPI) |
| { |
| this.compAPI = compAPI; |
| this.compAPI.setInternalAPIs(new APIs()); |
| this.compAPI.setExternalAPIs(new APIs()); |
| } |
| |
| public void startElement(String uri, String elementName, String qName, Attributes attributes) throws SAXException |
| { |
| if (elementName.equals(ELEMENT_METHOD_API) || qName.equals(ELEMENT_METHOD_API)) |
| { |
| MethodAPI methodAPI = new MethodAPI(); |
| startMethod(classAPI, methodAPI, attributes); |
| } |
| else if (elementName.equals(ELEMENT_FIELD_API) || qName.equals(ELEMENT_FIELD_API)) |
| { |
| FieldAPI fieldAPI = new FieldAPI(); |
| startField(classAPI, fieldAPI, attributes); |
| } |
| else if (elementName.equals(ELEMENT_CLASS_API) || qName.equals(ELEMENT_CLASS_API)) |
| { |
| if (packageAPI != null) |
| { |
| classAPI = new ClassAPI(); |
| classAPI.setName(attributes.getValue(ATTR_NAME)); |
| String attrAccess = attributes.getValue(ATTR_ACCESS); |
| if (attrAccess != null) |
| classAPI.setAccess(Integer.parseInt(attrAccess)); |
| String attrRef = attributes.getValue(ATTR_REFERENCE); |
| if (attrRef != null) |
| classAPI.setReference(Boolean.valueOf(attrRef)); |
| String attrImpl = attributes.getValue(ATTR_IMPLEMENT); |
| if (attrImpl != null) |
| classAPI.setImplement(Boolean.valueOf(attrImpl)); |
| String attrSubclass = attributes.getValue(ATTR_SUBCLASS); |
| if (attrSubclass != null) |
| classAPI.setSubclass(Boolean.valueOf(attrSubclass)); |
| String attrInstantiate = attributes.getValue(ATTR_INSTANTIATE); |
| if (attrInstantiate != null) |
| classAPI.setInstantiate(Boolean.valueOf(attrInstantiate)); |
| packageAPI.getClassAPIs().add(classAPI); |
| } |
| } |
| else if (elementName.equals(ELEMENT_PACKAGE_API) || qName.equals(ELEMENT_PACKAGE_API)) |
| { |
| if (apis != null) |
| { |
| packageAPI = new PackageAPI(); |
| packageAPI.setName(attributes.getValue(ATTR_NAME)); |
| apis.getPackageAPIs().add(packageAPI); |
| } |
| } |
| else if (elementName.equals(ELEMENT_INTERNAL_API) || qName.equals(ELEMENT_INTERNAL_API)) |
| { |
| apis = compAPI.getInternalAPIs(); |
| } |
| else if (elementName.equals(ELEMENT_EXTERNAL_API) || qName.equals(ELEMENT_EXTERNAL_API)) |
| { |
| apis = compAPI.getExternalAPIs(); |
| } |
| else if (equalsLocalpart(elementName, ELEMENT_COMPONENT_API) || equalsLocalpart(qName, ELEMENT_COMPONENT_API)) |
| { |
| compAPI.setName(attributes.getValue(ATTR_NAME)); |
| } |
| } |
| |
| private boolean equalsLocalpart(String fullname, String localpart) |
| { |
| int index = fullname.indexOf(':'); |
| if (index != -1) |
| return fullname.substring(index + 1).equals(localpart); |
| else |
| return fullname.equals(localpart); |
| } |
| |
| protected void startMethod(ClassAPI cAPI, MethodAPI methodAPI, Attributes attributes) throws SAXException |
| { |
| if (cAPI != null) |
| { |
| methodAPI.setName(attributes.getValue(ATTR_NAME)); |
| methodAPI.setDescriptor(attributes.getValue(ATTR_DESCRIPTOR)); |
| String attrAccess = attributes.getValue(ATTR_ACCESS); |
| if (attrAccess != null) |
| methodAPI.setAccess(Integer.parseInt(attrAccess)); |
| String attrThrows = attributes.getValue(ATTR_THROWS); |
| if (attrThrows != null) |
| addToList(methodAPI.getThrows(), attrThrows, " "); |
| cAPI.getMethodAPIs().add(methodAPI); |
| } |
| } |
| |
| protected void addToList(List list, String value, String delimiter) |
| { |
| StringTokenizer st = new StringTokenizer(value, delimiter); |
| while (st.hasMoreTokens()) |
| list.add(st.nextToken()); |
| } |
| |
| protected void startField(ClassAPI cAPI, FieldAPI fAPI, Attributes attributes) throws SAXException |
| { |
| if (cAPI != null) |
| { |
| fAPI.setName(attributes.getValue(ATTR_NAME)); |
| fAPI.setDescriptor(attributes.getValue(ATTR_DESCRIPTOR)); |
| String attrAccess = attributes.getValue(ATTR_ACCESS); |
| if (attrAccess != null) |
| fAPI.setAccess(Integer.parseInt(attrAccess)); |
| cAPI.getFieldAPIs().add(fAPI); |
| } |
| } |
| } |
| } |