| //------------------------------------------------------------------------------ |
| // Copyright (c) 2005, 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 implementation |
| //------------------------------------------------------------------------------ |
| package org.eclipse.epf.library.layout; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.OutputStreamWriter; |
| import java.io.StringWriter; |
| import java.io.UnsupportedEncodingException; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Properties; |
| |
| import org.eclipse.epf.common.utils.I18nUtil; |
| import org.eclipse.epf.common.utils.Timer; |
| import org.eclipse.epf.common.xml.XSLTProcessor; |
| import org.eclipse.epf.library.LibraryPlugin; |
| import org.eclipse.epf.library.LibraryResources; |
| import org.eclipse.epf.library.layout.util.XmlElement; |
| import org.eclipse.epf.library.layout.util.XmlHelper; |
| import org.eclipse.epf.library.prefs.PreferenceUtil; |
| import org.eclipse.epf.library.util.LibraryUtil; |
| import org.eclipse.epf.library.util.ResourceHelper; |
| import org.eclipse.epf.uma.MethodElement; |
| |
| import com.ibm.icu.util.Calendar; |
| |
| |
| /** |
| * Generates the HTML page for a Method element. |
| * |
| * @author Jinhua Xi |
| * @author Kelvin Low |
| * @since 1.0 |
| */ |
| public class HtmlBuilder { |
| |
| private boolean debug = false; |
| |
| private Properties xslParams = null; |
| |
| private ElementLayoutManager mgr = null; |
| |
| private ElementLayoutManager internal_mgr = null; |
| |
| //private ContentResourceScanner scanner = null; |
| |
| private boolean scanContent = true; |
| |
| // If true, display the "Show tree browse" image/link to the right of a |
| // published page. |
| private boolean showTreeBrowser = false; |
| |
| //private IContentValidator validator = null; |
| |
| // override this path to specify xsl path |
| private String layoutXslRootPath = LibraryPlugin.getDefault().getLayoutXslPath(); |
| |
| /** |
| * Creates a new instance. |
| */ |
| public HtmlBuilder() { |
| this(null); |
| } |
| |
| /** |
| * Creates a new instance. |
| */ |
| public HtmlBuilder(ElementLayoutManager mgr) { |
| init(); |
| setLayoutManager(mgr); |
| } |
| |
| public void setLayoutXslRootPath(String path) { |
| try { |
| if ( path != null && path.length() > 0 ) { |
| this.layoutXslRootPath = path; |
| if ( !this.layoutXslRootPath.endsWith(File.separator) ) { |
| this.layoutXslRootPath += File.separator; |
| } |
| |
| // get the localized file |
| File file = new File(this.layoutXslRootPath, "resources.properties"); //$NON-NLS-1$ |
| Locale locale = Locale.getDefault(); |
| String localFileName = I18nUtil.getLocalizedFile(file.getAbsolutePath(), locale); |
| if ( localFileName != null ) { |
| file = new File(localFileName); |
| } |
| if (file.exists()) { |
| xslParams.load(new FileInputStream(file)); |
| } |
| |
| // the PreferenceUtil also uses the xsl properties for activity breakdown layout |
| // so set it as well |
| PreferenceUtil.setXslProperties(xslParams); |
| } |
| } catch (IOException e) { |
| } |
| } |
| |
| /** |
| * Performs the necessary initialization. |
| */ |
| protected void init() { |
| debug = LibraryPlugin.getDefault().isDebugging(); |
| loadDefaultLayoutXsl(); |
| } |
| |
| public void loadDefaultLayoutXsl() { |
| layoutXslRootPath = LibraryPlugin.getDefault().getLayoutXslPath(); |
| try { |
| xslParams = LibraryPlugin.getDefault().getProperties( |
| "/layout/xsl/resources.properties"); //$NON-NLS-1$ |
| |
| // add the colon property, |
| xslParams.put("colon_with_space", LibraryResources.colon_with_space); //$NON-NLS-1$ |
| |
| // the PreferenceUtil also uses the xsl properties for activity breakdown layout |
| // so set it as well |
| PreferenceUtil.setXslProperties(xslParams); |
| |
| |
| } catch (IOException e) { |
| xslParams = null; |
| } |
| } |
| |
| /** |
| * Returns the publish directory. |
| */ |
| public String getPublishDir() { |
| return (mgr == null) ? null : mgr.getPublishDir(); |
| } |
| |
| /** |
| * Returns the publish directory. |
| */ |
| public void setPublishDir(String dir) { |
| if (mgr != null) { |
| mgr.setPublishDir(dir); |
| } |
| |
| //getScanner().setTargetRootPath(new File(getPublishDir())); |
| |
| // Reset the validator's publish dir. |
| getValidator().setPublishDir(dir); |
| } |
| |
| // /** |
| // * Sets the content validator. |
| // */ |
| // public void setValidator(IContentValidator validator) { |
| // this.validator = validator; |
| // getScanner().setValidator(this.validator); |
| // } |
| |
| /** |
| * Returns the content validator. |
| */ |
| public IContentValidator getValidator() { |
| // if (validator == null) { |
| // validator = new DefaultContentValidator(getPublishDir()); |
| // } |
| // return validator; |
| |
| return this.mgr.getValidator(); |
| } |
| |
| // /** |
| // * Returns the content resource scanner for the element. |
| // */ |
| // private ContentResourceScanner getScanner(MethodElement owner) { |
| // ILibraryResourceManager resMgr = ResourceHelper.getResourceMgr(owner); |
| // if ( resMgr == null ) { |
| // return null; |
| // } |
| // |
| // String rootContentPath = resMgr.getLogicalPluginPath(owner); |
| // File src_root = new File(resMgr.getPhysicalPluginPath(owner)); |
| // File tgt_root = new File(getPublishDir(), rootContentPath); |
| // ContentResourceScanner scanner = new ContentResourceScanner(src_root, tgt_root, rootContentPath, getValidator()); |
| // |
| // return scanner; |
| // } |
| |
| /** |
| * Sets the flag to display the "Show tree browser" image/link. |
| */ |
| public void enableTreeBrowser(boolean flag) { |
| this.showTreeBrowser = flag; |
| } |
| |
| /** |
| * Enables content scanning. |
| */ |
| public void enableContentScan(boolean scan) { |
| this.scanContent = scan; |
| } |
| |
| /** |
| * Returns <code>true</code> if content scanning is enabled. |
| */ |
| public boolean contentScanEnabled() { |
| return scanContent; |
| } |
| |
| /** |
| * Sets the Element Layout Manager. |
| * <p> |
| * A Element Layout Manager is associated with a configuration. |
| */ |
| public void setLayoutManager(ElementLayoutManager mgr) { |
| this.mgr = mgr; |
| if (this.mgr == null) { |
| this.mgr = getDefaultLayoutManager(); |
| } |
| |
| // Update the scanner target path. |
| //getScanner().setTargetRootPath(new File(getPublishDir())); |
| |
| // Reset the validator pub dir. |
| getValidator().setPublishDir(getPublishDir()); |
| } |
| |
| /** |
| * Returns the default Element Layout Manager. |
| */ |
| private ElementLayoutManager getDefaultLayoutManager() { |
| if ( this.internal_mgr == null ) { |
| this.internal_mgr = new ElementLayoutManager(); |
| } |
| |
| return this.internal_mgr; |
| } |
| |
| /** |
| * Returns the Element Layout Manager. |
| */ |
| public ElementLayoutManager getLayoutManager() { |
| if (this.mgr == null) { |
| this.mgr = getDefaultLayoutManager(); |
| } |
| return mgr; |
| } |
| |
| /** |
| * Generates the HTML for a Method element. |
| * |
| * @param element |
| * A Method element. |
| * @return A url of the generated content HTML file. |
| */ |
| public String generateHtml(MethodElement element) { |
| String url = null; |
| if (debug) { |
| long startTime = System.currentTimeMillis(); |
| IElementLayout layout = getLayoutManager().getLayout(element, true); |
| url = generateHtml(layout); |
| long endTime = System.currentTimeMillis(); |
| System.out |
| .println("Time taken to render HTML page for " + element.getName() + //$NON-NLS-1$ |
| ": " + (endTime - startTime) + " ms"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } else { |
| IElementLayout layout = getLayoutManager().getLayout(element, true); |
| url = generateHtml(layout); |
| } |
| return url; |
| } |
| |
| |
| /** |
| * Generates the HTML for a Method element. |
| * |
| * @param url |
| * The URL of a Method element. |
| */ |
| public void generateHtml(String url) { |
| IElementLayout layout = getLayoutManager().getLayout(url); |
| generateHtml(layout); |
| } |
| |
| /** |
| * Generates the HTML for a Method element. |
| * |
| * @param layout |
| * A Method Element. Layout object. |
| * @param linkedElements |
| * If not null, this object will be populated with a list of |
| * linked elements in the page. |
| * @return A url of the generated content HTML file. |
| */ |
| public String generateHtml(IElementLayout layout) { |
| if (layout == null) { |
| return "about:blank"; //$NON-NLS-1$ |
| } |
| |
| //System.out.println("*** generateHtml: " + LibraryUtil.getTypeName(layout.getElement()) ); |
| |
| // add time logging when publishing element |
| long time_start = Calendar.getInstance().getTimeInMillis(); |
| String elementPath = layout.getFilePath().replace('/', |
| File.separatorChar); |
| String elementPathName = elementPath |
| + layout.getFileName(ResourceHelper.FILE_EXT_HTML); |
| String filePath = this.getPublishDir() + elementPath; |
| String html_file = this.getPublishDir() + elementPathName; |
| |
| try { |
| |
| StringBuffer xml = getXml(layout); |
| |
| String xsl_uri; |
| |
| File f = new File(filePath); |
| if (!f.exists()) { |
| f.mkdirs(); |
| } |
| |
| // Generate the additonal outputs. |
| List layouts = layout.getLayouts(); |
| xsl_uri = layoutXslRootPath + layout.getXslUrl(); |
| generateHtml(layout, xsl_uri, html_file, xml); |
| |
| // Generate other layout files. |
| if (layouts != null && layouts.size() > 0) { |
| for (Iterator it = layouts.iterator(); it.hasNext();) { |
| LayoutInfo info = (LayoutInfo) it.next(); |
| xsl_uri = layoutXslRootPath + info.layout_xsl; |
| String file = filePath + info.fileName; |
| generateHtml(layout, xsl_uri, file, xml); |
| } |
| } |
| } catch (Exception e) { |
| e.printStackTrace(); |
| html_file = null; |
| } |
| |
| long time_end = Calendar.getInstance().getTimeInMillis(); |
| long mini_seconds = time_end - time_start; |
| if (mini_seconds > 1000) { |
| String msg = mini_seconds |
| + " mini-second(s) publishing element " + LibraryUtil.getTypeName(layout.getElement()) + "[" + elementPathName + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| IContentValidator validator = getValidator(); |
| if (validator == null) { |
| System.out.println(msg); |
| } else { |
| validator.logInfo(msg); |
| } |
| } |
| if (html_file != null) { |
| return html_file; |
| } |
| |
| return "about:blank"; //$NON-NLS-1$ |
| } |
| |
| /** |
| * Generates the HTML for a Method element. |
| * |
| * @param layout |
| * A Method Element. Layout object. |
| * @param xslURI |
| * The XSL stylesheet. |
| * @param htmlFile |
| * The HTML file to be generated. |
| * @param xml |
| * The XML buffer. |
| * @return A url of the generated content HTML file. |
| */ |
| private void generateHtml(IElementLayout layout, |
| String xsl_uri, String html_file, StringBuffer xml) { |
| Throwable th = null; |
| if (layout == null) { |
| return; |
| } |
| |
| Timer timer = null; |
| if ( debug ) { |
| timer = new Timer(); |
| } |
| |
| try { |
| StringWriter sw = new StringWriter(); |
| XSLTProcessor.transform(xsl_uri, xml.toString(), xslParams, sw); |
| sw.flush(); |
| String content = sw.getBuffer().toString(); |
| |
| if ( debug) { |
| timer.stop(); |
| System.out.println(timer.getTime() + " mini seconds for xml/xslt transformation"); //$NON-NLS-1$ |
| timer.start(); |
| } |
| // Always validate and fix the content before publishing. |
| content = ResourceHelper.validateContent(layout.getElement(), |
| content, getValidator(), layout.getLayoutMgr() |
| .getConfiguration(), this.layoutXslRootPath); |
| if (contentScanEnabled()) { |
| // scanContentForResources(layout.getElement(), content, layout |
| // .getFilePath()); |
| getValidator().scanContent(layout, content); |
| } |
| |
| if ( debug) { |
| timer.stop(); |
| System.out.println(timer.getTime() + " mini seconds scanning content"); //$NON-NLS-1$ |
| timer.start(); |
| } |
| |
| OutputStreamWriter output = new OutputStreamWriter( |
| new FileOutputStream(html_file), "utf-8"); //$NON-NLS-1$ |
| output.write(content); |
| output.flush(); |
| output.close(); |
| } catch (UnsupportedEncodingException e) { |
| e.printStackTrace(); |
| th = e; |
| } catch (FileNotFoundException e) { |
| e.printStackTrace(); |
| th = e; |
| } catch (IOException e) { |
| e.printStackTrace(); |
| th = e; |
| } catch (Exception e) { |
| e.printStackTrace(); |
| th = e; |
| } |
| |
| if (th != null) { |
| this.getValidator().logError(layout.getElement(), |
| "Error generating element content", th); //$NON-NLS-1$ |
| } |
| } |
| |
| /** |
| * Generates the HTML for a Method element. |
| * |
| * @param layout |
| * A Method Element. Layout object. |
| * @return A url of the generated content HTML file. |
| */ |
| private StringBuffer getXml(IElementLayout layout) { |
| StringBuffer xml = new StringBuffer(); |
| XmlElement xmlElement = layout.getXmlElement(true); |
| |
| // set the language attribute |
| Locale locale = Locale.getDefault(); |
| String lang = locale.getLanguage(); |
| xmlElement.setAttribute("lang", lang); //$NON-NLS-1$ |
| |
| if (showTreeBrowser) { |
| xmlElement.setAttribute("showTreeBrowser", "true"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| xml.append(XmlHelper.XML_HEADER).append(xmlElement.toXml()); |
| |
| if ( debug ) { |
| try { |
| String xml_file = this.getPublishDir() + "xml" + File.separator; //$NON-NLS-1$ |
| xml_file += layout.getType() + "." + layout.getFileName(".xml"); //$NON-NLS-1$ //$NON-NLS-2$ |
| File xf = new File(xml_file); |
| if ( !xf.exists() ) |
| { |
| xf.getParentFile().mkdirs(); |
| xf.createNewFile(); |
| } |
| |
| OutputStreamWriter output = new OutputStreamWriter( |
| new FileOutputStream(xf), "utf-8"); //$NON-NLS-1$ |
| output.write(xml.toString()); |
| output.flush(); |
| output.close(); |
| |
| // FileWriter xw = new FileWriter(xml_file); |
| // xw.write(xml.toString()); |
| // xw.flush(); |
| // xw.close(); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| } |
| |
| return xml; |
| } |
| |
| // /** |
| // * Scans the content for resource references. |
| // */ |
| // private void scanContentForResources(MethodElement owner, String content, |
| // String contentPath) { |
| // ContentResourceScanner scanner = getScanner(owner); |
| // if ( scanner != null ) { |
| // scanner.resolveResources(owner, content, contentPath); |
| // } |
| // } |
| |
| public void dispose() { |
| // if (validator != null) { |
| // validator.dispose(); |
| // } |
| |
| if ( internal_mgr != null ) { |
| internal_mgr.clear(); |
| internal_mgr = null; |
| } |
| |
| mgr = null; |
| // scanner = null; |
| // validator = null; |
| } |
| } |