blob: 4ad8ccc3973a7acefe79a5822a5b235637f236b3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 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.jdt.internal.ui.javadocexport;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.util.Assert;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
public class JavadocWriter {
private static final char PATH_SEPARATOR= '/'; // use forward slash for all platforms
private OutputStream fOutputStream;
private IJavaProject[] fJavaProjects;
private IPath fBasePath;
/**
* Create a JavadocWriter on the given output stream.
* It is the client's responsibility to close the output stream.
* @param basePath The base path to which all path will be made relative (if
* possible). If <code>null</code>, paths are not made relative.
*/
public JavadocWriter(OutputStream outputStream, IPath basePath, IJavaProject[] projects) {
Assert.isNotNull(outputStream);
fOutputStream= new BufferedOutputStream(outputStream);
fBasePath= basePath;
fJavaProjects= projects;
}
public void writeXML(JavadocOptionsManager store) throws ParserConfigurationException, TransformerException {
DocumentBuilder docBuilder= null;
DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
factory.setValidating(false);
docBuilder= factory.newDocumentBuilder();
Document document= docBuilder.newDocument();
// Create the document
Element project= document.createElement("project"); //$NON-NLS-1$
document.appendChild(project);
project.setAttribute("default", "javadoc"); //$NON-NLS-1$ //$NON-NLS-2$
Element javadocTarget= document.createElement("target"); //$NON-NLS-1$
project.appendChild(javadocTarget);
javadocTarget.setAttribute("name", "javadoc"); //$NON-NLS-1$ //$NON-NLS-2$
Element xmlJavadocDesc= document.createElement("javadoc"); //$NON-NLS-1$
javadocTarget.appendChild(xmlJavadocDesc);
if (!store.isFromStandard())
xmlWriteDoclet(store, document, xmlJavadocDesc);
else
xmlWriteJavadocStandardParams(store, document, xmlJavadocDesc);
// Write the document to the stream
Transformer transformer=TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount","4"); //$NON-NLS-1$ //$NON-NLS-2$
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(fOutputStream);
transformer.transform(source, result);
}
//writes ant file, for now only worry about one project
private void xmlWriteJavadocStandardParams(JavadocOptionsManager store, Document document, Element xmlJavadocDesc) throws DOMException {
String destination= getPathString(Path.fromOSString(store.getDestination()));
xmlJavadocDesc.setAttribute(store.DESTINATION, destination);
xmlJavadocDesc.setAttribute(store.VISIBILITY, store.getAccess());
String source= store.getSource();
if (source.length() > 0 && !source.equals("-")) { //$NON-NLS-1$
xmlJavadocDesc.setAttribute(store.SOURCE, store.getSource());
}
xmlJavadocDesc.setAttribute(store.USE, booleanToString(store.getBoolean("use"))); //$NON-NLS-1$
xmlJavadocDesc.setAttribute(store.NOTREE, booleanToString(store.getBoolean("notree"))); //$NON-NLS-1$
xmlJavadocDesc.setAttribute(store.NONAVBAR, booleanToString(store.getBoolean("nonavbar"))); //$NON-NLS-1$
xmlJavadocDesc.setAttribute(store.NOINDEX, booleanToString(store.getBoolean("noindex"))); //$NON-NLS-1$
xmlJavadocDesc.setAttribute(store.SPLITINDEX, booleanToString(store.getBoolean("splitindex"))); //$NON-NLS-1$
xmlJavadocDesc.setAttribute(store.AUTHOR, booleanToString(store.getBoolean("author"))); //$NON-NLS-1$
xmlJavadocDesc.setAttribute(store.VERSION, booleanToString(store.getBoolean("version"))); //$NON-NLS-1$
xmlJavadocDesc.setAttribute(store.NODEPRECATEDLIST, booleanToString(store.getBoolean("nodeprecatedlist"))); //$NON-NLS-1$
xmlJavadocDesc.setAttribute(store.NODEPRECATED, booleanToString(store.getBoolean("nodeprecated"))); //$NON-NLS-1$
//set the packages and source files
List packages= new ArrayList();
List sourcefiles= new ArrayList();
sortSourceElement(store.getSourceElements(), sourcefiles, packages);
if (!packages.isEmpty())
xmlJavadocDesc.setAttribute(store.PACKAGENAMES, toSeparatedList(packages));
if (!sourcefiles.isEmpty())
xmlJavadocDesc.setAttribute(store.SOURCEFILES, toSeparatedList(sourcefiles));
xmlJavadocDesc.setAttribute(store.SOURCEPATH, getPathString(store.getSourcepath()));
xmlJavadocDesc.setAttribute(store.CLASSPATH, getPathString(store.getClasspath()));
String overview= store.getOverview();
if (overview.length() > 0)
xmlJavadocDesc.setAttribute(store.OVERVIEW, overview);
String styleSheet= store.getStyleSheet();
if (styleSheet.length() > 0)
xmlJavadocDesc.setAttribute(store.STYLESHEETFILE, styleSheet);
String title= store.getTitle();
if (title.length() > 0)
xmlJavadocDesc.setAttribute(store.TITLE, title);
String vmArgs= store.getVMParams();
String additionalArgs= store.getAdditionalParams();
if (vmArgs.length() + additionalArgs.length() > 0) {
String str= vmArgs + ' ' + additionalArgs;
xmlJavadocDesc.setAttribute(store.EXTRAOPTIONS, str);
}
String[] hrefs= store.getHRefs();
for (int i= 0; i < hrefs.length; i++) {
Element links= document.createElement("link"); //$NON-NLS-1$
xmlJavadocDesc.appendChild(links);
links.setAttribute(store.HREF, hrefs[i]);
}
}
private void sortSourceElement(IJavaElement[] iJavaElements, List sourcefiles, List packages) {
for (int i= 0; i < iJavaElements.length; i++) {
IJavaElement element= iJavaElements[i];
IPath p= element.getResource().getLocation();
if (p == null)
continue;
if (element instanceof ICompilationUnit) {
String relative= getPathString(p);
sourcefiles.add(relative);
} else if (element instanceof IPackageFragment) {
packages.add(element.getElementName());
}
}
}
private String getPathString(IPath[] paths) {
StringBuffer buf= new StringBuffer();
for (int i= 0; i < paths.length; i++) {
if (buf.length() != 0) {
buf.append(File.pathSeparatorChar);
}
buf.append(getPathString(paths[i]));
}
if (buf.length() == 0) {
buf.append('.');
}
return buf.toString();
}
private boolean hasSameDevice(IPath p1, IPath p2) {
String dev= p1.getDevice();
if (dev == null) {
return p2.getDevice() == null;
}
return dev.equals(p2.getDevice());
}
//make the path relative to the base path
private String getPathString(IPath fullPath) {
if (fBasePath == null || !hasSameDevice(fullPath, fBasePath)) {
return fullPath.toOSString();
}
int matchingSegments= fBasePath.matchingFirstSegments(fullPath);
if (fBasePath.segmentCount() == matchingSegments) {
return getRelativePath(fullPath, matchingSegments);
}
for (int i= 0; i < fJavaProjects.length; i++) {
IProject proj= fJavaProjects[i].getProject();
IPath projLoc= proj.getLocation();
if (projLoc.segmentCount() <= matchingSegments && projLoc.isPrefixOf(fullPath)) {
return getRelativePath(fullPath, matchingSegments);
}
}
IPath workspaceLoc= ResourcesPlugin.getWorkspace().getRoot().getLocation();
if (workspaceLoc.segmentCount() <= matchingSegments && workspaceLoc.isPrefixOf(fullPath)) {
return getRelativePath(fullPath, matchingSegments);
}
return fullPath.toOSString();
}
private String getRelativePath(IPath fullPath, int matchingSegments) {
StringBuffer res= new StringBuffer();
int backSegments= fBasePath.segmentCount() - matchingSegments;
while (backSegments > 0) {
res.append(".."); //$NON-NLS-1$
res.append(PATH_SEPARATOR);
backSegments--;
}
int segCount= fullPath.segmentCount();
for (int i= matchingSegments; i < segCount; i++) {
if (i > matchingSegments) {
res.append(PATH_SEPARATOR);
}
res.append(fullPath.segment(i));
}
return res.toString();
}
private void xmlWriteDoclet(JavadocOptionsManager store, Document document, Element xmlJavadocDesc) throws DOMException {
//set the packages and source files
List packages= new ArrayList();
List sourcefiles= new ArrayList();
sortSourceElement(store.getSourceElements(), sourcefiles, packages);
if (!packages.isEmpty())
xmlJavadocDesc.setAttribute(store.PACKAGENAMES, toSeparatedList(packages));
if (!sourcefiles.isEmpty())
xmlJavadocDesc.setAttribute(store.SOURCEFILES, toSeparatedList(sourcefiles));
xmlJavadocDesc.setAttribute(store.SOURCEPATH, getPathString(store.getSourcepath()));
xmlJavadocDesc.setAttribute(store.CLASSPATH, getPathString(store.getClasspath()));
xmlJavadocDesc.setAttribute(store.VISIBILITY, store.getAccess());
Element doclet= document.createElement("doclet"); //$NON-NLS-1$
xmlJavadocDesc.appendChild(doclet);
doclet.setAttribute(store.NAME, store.getDocletName());
doclet.setAttribute(store.PATH, store.getDocletPath());
String str= store.getOverview();
if (str.length() > 0) //$NON-NLS-1$
xmlJavadocDesc.setAttribute(store.OVERVIEW, str);
str= store.getAdditionalParams();
if (str.length() > 0) //$NON-NLS-1$
xmlJavadocDesc.setAttribute(store.EXTRAOPTIONS, str);
}
private String toSeparatedList(List packages) {
StringBuffer buf= new StringBuffer();
Iterator iter= packages.iterator();
int nAdded= 0;
while (iter.hasNext()) {
if (nAdded > 0) {
buf.append(',');
}
nAdded++;
String curr= (String) iter.next();
buf.append(curr);
}
return buf.toString();
}
private String booleanToString(boolean bool) {
if (bool)
return "true"; //$NON-NLS-1$
else
return "false"; //$NON-NLS-1$
}
public void close() throws IOException {
if (fOutputStream != null) {
fOutputStream.close();
}
}
}