/* * JBoss by Red Hat * Copyright 2006-2009, Red Hat Middleware, LLC, and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.ide.eclipse.freemarker.configuration; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.Path; import org.jboss.ide.eclipse.freemarker.Plugin; import org.jboss.ide.eclipse.freemarker.model.LibraryMacroDirective; import org.jboss.ide.eclipse.freemarker.model.MacroDirective; import org.jboss.ide.eclipse.freemarker.util.StringUtil; import org.w3c.dom.Element; /** * @author <a href="mailto:joe@binamics.com">Joe Hudson</a> */ public class MacroLibrary { public static final String TYPE_FILE = "file"; //$NON-NLS-1$ public static final String TYPE_JAR_ENTRY = "jarEntry"; //$NON-NLS-1$ private long lastUpdatedTime; private IFile file; private String content; private String path; private String namespace; private String type; private MacroDirective[] macros; public MacroLibrary (String namespace, IFile file) throws IOException, CoreException { this.namespace = namespace; this.file = file; this.content = StringUtil.getStringFromStream(file.getContents(true)); this.type = TYPE_FILE; } public MacroLibrary (String namespace, InputStream is, String path, String type) throws IOException { this.namespace = namespace; this.content = StringUtil.getStringFromStream(is); this.type = type; this.path = path; if (null == this.type) this.type = TYPE_FILE; } public synchronized MacroDirective[] getMacros() { if (null == macros || isStale()) { load(); } return macros; } public boolean isStale () { return (null != file && file.getModificationStamp() > lastUpdatedTime); } public IFile getFile () { return file; } private void load () { try { List macros = new ArrayList(); String search = "#macro "; //$NON-NLS-1$ int index = content.indexOf(search); int startIndex = index; char startChar = content.charAt(index-1); char endChar; if (startChar == '[') endChar = ']'; else endChar = '>'; while (startIndex > 0) { int stackCount = 0; boolean inString = false; // find the end int endIndex = Integer.MIN_VALUE; boolean escape = false; while (content.length() > index && index >= 0) { boolean doEscape = false; char c = content.charAt(index++); if (!escape) { if (c == '\"') inString = !inString; else if (c == '\\' && inString) doEscape = true; else if (c == startChar) stackCount ++; else if (c == endChar) { if (stackCount > 0) stackCount --; else { endIndex = index-1; break; } } } escape = doEscape; } if (endIndex > 0) { String sub = content.substring(startIndex, endIndex); MacroDirective macroDirective = new LibraryMacroDirective(namespace, sub, startIndex-1, endIndex-index+2); macros.add(macroDirective); index = content.indexOf(startChar + search, endIndex); if (index >= 0) index++; startIndex = index; endIndex = Integer.MIN_VALUE; } else { break; } } this.macros = (MacroDirective[]) macros.toArray( new MacroDirective[macros.size()]); if (null != file) this.lastUpdatedTime = file.getModificationStamp(); } catch (Exception e) { macros = new MacroDirective[0]; Plugin.log(e); } } public String getNamespace() { return namespace; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String toXML () { StringBuffer sb = new StringBuffer(); sb.append("<entry namespace=\"" + getNamespace() + "\" "); //$NON-NLS-1$ //$NON-NLS-2$ sb.append("path=\"" + getPath() + "\" "); //$NON-NLS-1$ //$NON-NLS-2$ if (null != file) { sb.append("project=\"" + file.getProject().getName() + "\" "); //$NON-NLS-1$ //$NON-NLS-2$ } sb.append("type=\"" + getType() + "\"/>"); //$NON-NLS-1$//$NON-NLS-2$ return sb.toString(); } public String getPath () { if (null != file) return file.getProjectRelativePath().toString(); else return path; } public static MacroLibrary fromXML (IProject project, Element node, ClassLoader classLoader) throws CoreException, IOException { String namespace = node.getAttribute("namespace"); //$NON-NLS-1$ String path = node.getAttribute("path"); //$NON-NLS-1$ String projectName = node.getAttribute("project"); //$NON-NLS-1$ String type = node.getAttribute("type"); //$NON-NLS-1$ if (null == type || type.length() == 0 || type.equals(TYPE_FILE)) { if (null != projectName && projectName.length() > 0) project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); IFile file = project.getFile(new Path(path)); if (null == file || !file.exists()) return null; else return new MacroLibrary(namespace, file); } else if (type.equals(TYPE_JAR_ENTRY)) { InputStream is = classLoader.getResourceAsStream(path); if (null != is) { return new MacroLibrary(namespace, is, path, TYPE_JAR_ENTRY); } else return null; } else return null; } }