/*****************************************************************************
* Copyright (c) 2006-2007, Cloudsmith Inc.
* The code, documentation and other materials contained herein have been
* licensed under the Eclipse Public License - v 1.0 by the copyright holder
* listed above, as the Initial Contributor under such license. The text of
* such license is available at www.eclipse.org.
*****************************************************************************/
package org.eclipse.buckminster.jnlp.componentinfo.cloudsmith;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.Map;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.codec.binary.Base64;
import org.eclipse.buckminster.core.helpers.FileUtils;
import org.eclipse.buckminster.jnlp.Messages;
import org.eclipse.buckminster.jnlp.componentinfo.IComponentInfoProvider;
import org.eclipse.buckminster.jnlp.ui.UiUtils;
import org.eclipse.buckminster.opml.IBody;
import org.eclipse.buckminster.opml.IOPML;
import org.eclipse.buckminster.opml.IOutline;
import org.eclipse.buckminster.opml.OutlineType;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.osgi.util.NLS;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
/**
* @author Karel Brezina
*
*/
public class ComponentInfoProvider implements IComponentInfoProvider
{
private static final String SRC_HTML_FOLDER = "html"; //$NON-NLS-1$
private static final String SRC_HTML_IMG_FOLDER = "html" + IPath.SEPARATOR + "img"; //$NON-NLS-1$ //$NON-NLS-2$
private static final String IMG_FOLDER = "img"; //$NON-NLS-1$
private static final String HTML_TEMPLATE = "componentinfo.page.template.html"; //$NON-NLS-1$
private static final String HTML_ENCODING = "UTF-8"; //$NON-NLS-1$
private static final String HTML_DOCTYPE_PUBLIC = "-//W3C//DTD XHTML 1.0 Strict//EN"; //$NON-NLS-1$
private static final String HTML_DOCTYPE_SYSTEM = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"; //$NON-NLS-1$
private static final String HTML_BASEPATH_PLACEHOLDER = "#{basePath}"; //$NON-NLS-1$
private static final String IMG_FOOTER = "footer.bar.2.png"; //$NON-NLS-1$
private static final String IMG_FAVICON = "favicon.ico"; //$NON-NLS-1$
private static final String IMG_LOGO = "logotype.2.png"; //$NON-NLS-1$
private static final String IMG_RSS = "rsslink.gif"; //$NON-NLS-1$
private static final String PROP_PROVIDER_LOGO_URL = "providerLogo"; //$NON-NLS-1$
private static final String PROP_ARTIFACT_NAME = "artifactName"; //$NON-NLS-1$
private static final String PROP_CSPEC_NAME = "cspecName"; //$NON-NLS-1$
private static final String PROP_CSPEC_VERSION_STRING = "cspecVersionString"; //$NON-NLS-1$
private static final String PROP_BASE_PATH_URL = "basePathURL"; //$NON-NLS-1$
private static final String PROP_HOME_PAGE_URL = "homePageURL"; //$NON-NLS-1$
private static final String PROP_CLOUDPAGE_URL = "cloudpageURL"; //$NON-NLS-1$
private static final String ID_HOME_PAGE_URL = "homeLink"; //$NON-NLS-1$
private static final String ID_CLOUDPAGE_URL = "cloudpageLink"; //$NON-NLS-1$
private static final String ID_DISTRO_NAME = "distroNameField"; //$NON-NLS-1$
private static final String ID_DISTRO_VERSION = "distroVersionField"; //$NON-NLS-1$
private static final String ID_FEED_TABLE = "feedTable"; //$NON-NLS-1$
private static final String TAG_TR = "tr"; //$NON-NLS-1$
private static final String TAG_TD = "td"; //$NON-NLS-1$
private static final String TAG_A = "a"; //$NON-NLS-1$
private static final String TAG_IMG = "img"; //$NON-NLS-1$
private static final String ATTR_HREF = "href"; //$NON-NLS-1$
private static final String ATTR_VALUE = "value"; //$NON-NLS-1$
private static final String ATTR_SRC = "src"; //$NON-NLS-1$
private static final String ATTR_CLASS = "class"; //$NON-NLS-1$
private static final String ATTR_ALT = "alt"; //$NON-NLS-1$
private static final String ATTR_TITLE = "title"; //$NON-NLS-1$
private static final String CELL_1 = "Cell-1"; //$NON-NLS-1$
private static final String CELL_N = "Cell-n"; //$NON-NLS-1$
private static final String NBSP_VALUE = "\u00A0"; //$NON-NLS-1$
private static final String CLASS_BLUE_LINK = "BlueLink"; //$NON-NLS-1$
private static InputStream getResource(String resourcePath)
{
return ComponentInfoProvider.class.getResourceAsStream(resourcePath);
}
private final IProgressMonitor m_nullMonitor = new NullProgressMonitor();
private Document m_xml;
private Map<String, String> m_properties;
private IOPML m_opml;
public String prepareHTML(Map<String, String> properties, IOPML opml, String destination) throws Exception
{
if(opml == null)
return null;
if(properties == null)
throw new IllegalArgumentException(Messages.properties_are_not_set);
if(destination == null)
throw new IllegalArgumentException(Messages.target_destination_is_not_set);
m_properties = properties;
m_opml = opml;
String htmlURL = null;
InputStream is = getResource(IPath.SEPARATOR + SRC_HTML_FOLDER + IPath.SEPARATOR + HTML_TEMPLATE);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
FileUtils.copyFile(is, bos, m_nullMonitor);
String string = bos.toString(HTML_ENCODING);
String basePath = m_properties.get(PROP_BASE_PATH_URL);
if(basePath == null)
throw new Exception(NLS.bind(Messages.missing_required_property_0, PROP_BASE_PATH_URL));
string = string.replaceAll(Pattern.quote(HTML_BASEPATH_PLACEHOLDER), basePath);
m_xml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
new ByteArrayInputStream(string.getBytes(HTML_ENCODING)));
fillTemplate();
File htmlDestDir = new File(destination);
if(!(htmlDestDir.exists() && htmlDestDir.isDirectory()))
FileUtils.createDirectory(htmlDestDir, m_nullMonitor);
File imgDestDir = new File(htmlDestDir, "img"); //$NON-NLS-1$
if(!(imgDestDir.exists() && imgDestDir.isDirectory()))
FileUtils.createDirectory(imgDestDir, m_nullMonitor);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
StreamResult result = new StreamResult(stream);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, HTML_ENCODING);
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, HTML_DOCTYPE_PUBLIC);
transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, HTML_DOCTYPE_SYSTEM);
transformer.transform(new DOMSource(m_xml), result);
String htmlFileName = "distro." + m_properties.get(PROP_CSPEC_NAME) + "." //$NON-NLS-1$ //$NON-NLS-2$
+ m_properties.get(PROP_CSPEC_VERSION_STRING) + ".html"; //$NON-NLS-1$
htmlFileName = htmlFileName.replaceAll("(?:/|\\\\|:|\\*|\\?|\"|<|>|\\|)", "_"); //$NON-NLS-1$ //$NON-NLS-2$
htmlURL = destination + File.separator + htmlFileName;
FileUtils.copyFile(new ByteArrayInputStream(stream.toByteArray()), htmlDestDir, htmlFileName, m_nullMonitor);
if(!new File(imgDestDir, IMG_FOOTER).exists())
FileUtils.copyFile(getResource(IPath.SEPARATOR + SRC_HTML_IMG_FOLDER + IPath.SEPARATOR + IMG_FOOTER),
imgDestDir, IMG_FOOTER, m_nullMonitor);
if(!new File(imgDestDir, IMG_FAVICON).exists())
FileUtils.copyFile(getResource(IPath.SEPARATOR + SRC_HTML_IMG_FOLDER + IPath.SEPARATOR + IMG_FAVICON),
imgDestDir, IMG_FAVICON, m_nullMonitor);
if(!new File(imgDestDir, IMG_RSS).exists())
FileUtils.copyFile(getResource(IPath.SEPARATOR + SRC_HTML_IMG_FOLDER + IPath.SEPARATOR + IMG_RSS),
imgDestDir, IMG_RSS, m_nullMonitor);
if(!new File(imgDestDir, IMG_LOGO).exists())
FileUtils.copyFile(new URL(m_properties.get(PROP_PROVIDER_LOGO_URL)).openStream(), imgDestDir, IMG_LOGO,
m_nullMonitor);
return htmlURL;
}
private Element addOutline(IOutline outline)
{
Element tr = null;
if(outline.getType() == OutlineType.RSS || outline.getType() == OutlineType.ATOM)
{
tr = m_xml.createElement(TAG_TR);
Element td = m_xml.createElement(TAG_TD);
tr.appendChild(td);
td.setAttribute(ATTR_CLASS, CELL_1);
td.setTextContent(outline.getText());
td = m_xml.createElement(TAG_TD);
tr.appendChild(td);
td.setAttribute(ATTR_CLASS, CELL_N);
String string = UiUtils.trimmedValue(outline.getDescription());
td.setTextContent(string == null
? NBSP_VALUE
: string);
td = m_xml.createElement(TAG_TD);
tr.appendChild(td);
td.setAttribute(ATTR_CLASS, CELL_N);
Element a = m_xml.createElement(TAG_A);
td.appendChild(a);
a.setAttribute(ATTR_HREF, outline.getXmlUrl().toString());
a.setAttribute(ATTR_CLASS, CLASS_BLUE_LINK);
a.setAttribute(ATTR_TITLE, outline.getDescription());
Element rssImg = m_xml.createElement(TAG_IMG);
a.appendChild(rssImg);
rssImg.setAttribute(ATTR_ALT, "rss icon"); //$NON-NLS-1$
rssImg.setAttribute(ATTR_SRC, IMG_FOLDER + IPath.SEPARATOR + IMG_RSS);
td = m_xml.createElement(TAG_TD);
tr.appendChild(td);
td.setAttribute(ATTR_CLASS, CELL_N);
a = m_xml.createElement(TAG_A);
td.appendChild(a);
a.setAttribute(ATTR_HREF, outline.getXmlUrl().toString());
a.setAttribute(ATTR_CLASS, CLASS_BLUE_LINK);
a.setAttribute(ATTR_TITLE, outline.getDescription());
Text linkText = m_xml.createTextNode("subscribe"); //$NON-NLS-1$
a.appendChild(linkText);
}
return tr;
}
private void addOutlines(Element tableElement, IBody body, int level)
{
if(body != null && body.getOutlines() != null)
for(IOutline outline : body.getOutlines())
{
Element childElement = addOutline(outline);
if(childElement != null)
tableElement.appendChild(childElement);
addOutlines(childElement, outline, level + 1);
}
}
private void fillTemplate()
{
setAttribute(ID_HOME_PAGE_URL, ATTR_HREF, PROP_HOME_PAGE_URL, false);
setAttribute(ID_CLOUDPAGE_URL, ATTR_HREF, PROP_CLOUDPAGE_URL, false);
setAttribute(ID_DISTRO_NAME, ATTR_VALUE, PROP_ARTIFACT_NAME, false);
setAttribute(ID_DISTRO_VERSION, ATTR_VALUE, PROP_CSPEC_VERSION_STRING, false);
Element element = m_xml.getElementById(ID_FEED_TABLE);
if(element != null)
if(m_opml != null)
addOutlines(element, m_opml.getBody(), 0);
}
private void setAttribute(String nodeId, String attibuteName, String propertyName, boolean base64)
{
Element element = m_xml.getElementById(nodeId);
if(element != null)
{
String value = m_properties.get(propertyName);
if(base64)
try
{
if(value != null && value.length() > 0)
value = new String(Base64.decodeBase64(value.getBytes()), "UTF-8"); //$NON-NLS-1$
}
catch(UnsupportedEncodingException e)
{
value = null;
e.printStackTrace();
}
if(attibuteName == null)
element.setTextContent(value);
else
element.setAttribute(attibuteName, value);
}
}
}