blob: 7cfb6b2ea52134fd8d55278056a887e7dc7c7ceb [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.web.jsps.parserapi;
import java.util.*;
import java.util.logging.Level;
//import org.apache.jasper.Constants;
import java.util.logging.Logger;
//import org.apache.jasper.Constants;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.TagInfo;
import javax.servlet.jsp.tagext.TagFileInfo;
import javax.servlet.jsp.tagext.FunctionInfo;
import javax.servlet.jsp.tagext.TagAttributeInfo;
import javax.servlet.jsp.tagext.TagLibraryInfo;
/**
* A repository for various info about the translation unit under compilation.
*
* @author Kin-man Chung, Petr Jiricka
*/
public abstract class PageInfo {
public static final String JSP_SERVLET_BASE = "javax.servlet.http.HttpServlet";
private static Comparator<TagFileInfo> TAG_FILE_INFO_COMPARATOR = new Comparator<TagFileInfo>() {
@Override
public int compare(TagFileInfo o1, TagFileInfo o2) {
return o1.getPath().compareTo(o2.getPath());
}
};
private List<String> imports;
private List<String> dependants;
// private BeanRepository beanRepository;
private BeanData[] beans;
private Map<String, TagLibraryInfo> taglibsMap;
private Map<String, String> jspPrefixMapper;
private Map<String, LinkedList<String>> xmlPrefixMapper;
/** Approximate XML prefix mapper. Same as xmlPrefixMapper, but does not "forget" mappings (by popping them). */
private Map approxXmlPrefixMapper;
private String defaultLanguage = "java";
private String language;
private String defaultExtends = JSP_SERVLET_BASE;
private String xtends;
private String contentType = null;
private String session;
private boolean isSession = true;
private String bufferValue;
private int buffer = 8*1024; // XXX confirm
private String autoFlush;
private boolean isAutoFlush = true;
private String isThreadSafeValue;
private boolean isThreadSafe = true;
private String isErrorPageValue;
private boolean isErrorPage = false;
private String errorPage = null;
private String info;
private boolean scriptless = false;
private boolean scriptingInvalid = false;
private String isELIgnoredValue;
private boolean isELIgnored = false;
private String omitXmlDecl = null;
private String doctypeName = null;
private String doctypePublic = null;
private String doctypeSystem = null;
private boolean isJspPrefixHijacked;
// Set of all element and attribute prefixes used in this translation unit
private Set<String> prefixes;
private boolean hasJspRoot = false;
private List includePrelude;
private List includeCoda;
private List<String> pluginDcls; // Id's for tagplugin declarations
// Adding for obtaining informations about the parsed tag file
private boolean isTagFile;
private TagInfo tagInfo;
public PageInfo(/*BeanRepository beanRepository*/
Map<String, TagLibraryInfo> taglibsMap,
Map<String, String> jspPrefixMapper,
Map<String, LinkedList<String>> xmlPrefixMapper,
Map approxXmlPrefixMapper,
List<String> imports,
List<String> dependants,
List includePrelude,
List includeCoda,
List<String> pluginDcls,
Set<String> prefixes
) {
//this.beanRepository = beanRepository;
this.taglibsMap = taglibsMap;
this.jspPrefixMapper = jspPrefixMapper;
this.xmlPrefixMapper = xmlPrefixMapper;
this.approxXmlPrefixMapper = approxXmlPrefixMapper;
this.imports = imports;
this.dependants = dependants;
this.includePrelude = includePrelude;
this.includeCoda = includeCoda;
this.pluginDcls = pluginDcls;
this.prefixes = prefixes;
this.isTagFile = false;
}
/**
* Check if the plugin ID has been previously declared. Make a not
* that this Id is now declared.
* @return true if Id has been declared.
*/
public boolean isPluginDeclared(String id) {
if (pluginDcls.contains(id))
return true;
pluginDcls.add(id);
return false;
}
public void addImports(List<String> imports) {
this.imports.addAll(imports);
}
public void addImport(String imp) {
this.imports.add(imp);
}
public List<String> getImports() {
return imports;
}
public void addDependant(String d) {
if (!dependants.contains(d))
dependants.add(d);
}
public List<String> getDependants() {
return dependants;
}
public void setScriptless(boolean s) {
scriptless = s;
}
public boolean isScriptless() {
return scriptless;
}
public void setScriptingInvalid(boolean s) {
scriptingInvalid = s;
}
public boolean isScriptingInvalid() {
return scriptingInvalid;
}
public List getIncludePrelude() {
return includePrelude;
}
public void setIncludePrelude(Vector prelude) {
includePrelude = prelude;
}
public List getIncludeCoda() {
return includeCoda;
}
public void setIncludeCoda(Vector coda) {
includeCoda = coda;
}
public void setHasJspRoot(boolean s) {
hasJspRoot = s;
}
public boolean hasJspRoot() {
return hasJspRoot;
}
public String getOmitXmlDecl() {
return omitXmlDecl;
}
public void setOmitXmlDecl(String omit) {
omitXmlDecl = omit;
}
public String getDoctypeName() {
return doctypeName;
}
public void setDoctypeName(String doctypeName) {
this.doctypeName = doctypeName;
}
public String getDoctypeSystem() {
return doctypeSystem;
}
public void setDoctypeSystem(String doctypeSystem) {
this.doctypeSystem = doctypeSystem;
}
public String getDoctypePublic() {
return doctypePublic;
}
public void setDoctypePublic(String doctypePublic) {
this.doctypePublic = doctypePublic;
}
/* Tag library and XML namespace management methods */
public void setIsJspPrefixHijacked(boolean isHijacked) {
isJspPrefixHijacked = isHijacked;
}
public boolean isJspPrefixHijacked() {
return isJspPrefixHijacked;
}
/*
* Adds the given prefix to the set of prefixes of this translation unit.
*
* @param prefix The prefix to add
*/
public void addPrefix(String prefix) {
prefixes.add(prefix);
}
/*
* Checks to see if this translation unit contains the given prefix.
*
* @param prefix The prefix to check
*
* @return true if this translation unit contains the given prefix, false
* otherwise
*/
public boolean containsPrefix(String prefix) {
return prefixes.contains(prefix);
}
/*
* Maps the given URI to the given tag library.
*
* @param uri The URI to map
* @param info The tag library to be associated with the given URI
*/
public void addTaglib(String uri, TagLibraryInfo info) {
taglibsMap.put(uri, info);
}
/*
* Gets the tag library corresponding to the given URI.
*
* @return Tag library corresponding to the given URI
*/
public TagLibraryInfo getTaglib(String uri) {
return taglibsMap.get(uri);
}
/*
* Gets the collection of tag libraries that are associated with a URI
*
* @return Collection of tag libraries that are associated with a URI
*/
public Collection<TagLibraryInfo> getTaglibs() {
return taglibsMap.values();
}
/*
* Checks to see if the given URI is mapped to a tag library.
*
* @param uri The URI to map
*
* @return true if the given URI is mapped to a tag library, false
* otherwise
*/
public boolean hasTaglib(String uri) {
return taglibsMap.containsKey(uri);
}
/*
* Maps the given prefix to the given URI.
*
* @param prefix The prefix to map
* @param uri The URI to be associated with the given prefix
*/
public void addPrefixMapping(String prefix, String uri) {
jspPrefixMapper.put(prefix, uri);
}
/*
* Pushes the given URI onto the stack of URIs to which the given prefix
* is mapped.
*
* @param prefix The prefix whose stack of URIs is to be pushed
* @param uri The URI to be pushed onto the stack
*/
public void pushPrefixMapping(String prefix, String uri) {
LinkedList<String> stack = xmlPrefixMapper.get(prefix);
if (stack == null) {
stack = new LinkedList<String>();
xmlPrefixMapper.put(prefix, stack);
}
stack.addFirst(uri);
}
/*
* Removes the URI at the top of the stack of URIs to which the given
* prefix is mapped.
*
* @param prefix The prefix whose stack of URIs is to be popped
*/
public void popPrefixMapping(String prefix) {
LinkedList<String> stack = xmlPrefixMapper.get(prefix);
if (stack == null || stack.size() == 0) {
// XXX throw new Exception("XXX");
}
stack.removeFirst();
}
/*
* Returns the URI to which the given prefix maps.
*
* @param prefix The prefix whose URI is sought
*
* @return The URI to which the given prefix maps
*/
public String getURI(String prefix) {
String uri = null;
LinkedList<String> stack = xmlPrefixMapper.get(prefix);
if (stack == null || stack.size() == 0) {
uri = jspPrefixMapper.get(prefix);
} else {
uri = stack.getFirst();
}
return uri;
}
/* Page/Tag directive attributes */
/*
* language
*/
public void setLanguage(String value) {
language = value;
}
public String getLanguage(boolean useDefault) {
return (language == null && useDefault ? defaultLanguage : language);
}
public String getLanguage() {
return getLanguage(true);
}
/*
* extends
*/
public void setExtends(String value) {
xtends = value;
/*
* If page superclass is top level class (i.e. not in a package)
* explicitly import it. If this is not done, the compiler will assume
* the extended class is in the same pkg as the generated servlet.
*/
//if (value.indexOf('.') < 0)
// n.addImport(value);
}
/**
* Gets the value of the 'extends' page directive attribute.
*
* @param useDefault TRUE if the default
* (org.apache.jasper.runtime.HttpJspBase) should be returned if this
* attribute has not been set, FALSE otherwise
*
* @return The value of the 'extends' page directive attribute, or the
* default (org.apache.jasper.runtime.HttpJspBase) if this attribute has
* not been set and useDefault is TRUE
*/
public String getExtends(boolean useDefault) {
return (xtends == null && useDefault ? defaultExtends : xtends);
}
/**
* Gets the value of the 'extends' page directive attribute.
*
* @return The value of the 'extends' page directive attribute, or the
* default (org.apache.jasper.runtime.HttpJspBase) if this attribute has
* not been set
*/
public String getExtends() {
return getExtends(true);
}
/*
* contentType
*/
public void setContentType(String value) {
contentType = value;
}
public String getContentType() {
return contentType;
}
/*
* buffer
*/
public void setBufferValue(String value) throws JspException {
if (value == null)
return;
if ("none".equalsIgnoreCase(value))
buffer = 0;
else {
if (value == null || !value.endsWith("kb"))
throw new JspException(value);
try {
Integer k = new Integer(value.substring(0, value.length()-2));
buffer = k * 1024;
} catch (NumberFormatException e) {
throw new JspException(value);
}
}
bufferValue = value;
}
public String getBufferValue() {
return bufferValue;
}
public int getBuffer() {
return buffer;
}
/*
* session
*/
public void setSession(String value) throws JspException {
if (value == null)
return;
if ("true".equalsIgnoreCase(value))
isSession = true;
else if ("false".equalsIgnoreCase(value))
isSession = false;
else
throw new JspException(value);
session = value;
}
public String getSession() {
return session;
}
public boolean isSession() {
return isSession;
}
/*
* autoFlush
*/
public void setAutoFlush(String value) throws JspException {
if (value == null)
return;
if ("true".equalsIgnoreCase(value))
isAutoFlush = true;
else if ("false".equalsIgnoreCase(value))
isAutoFlush = false;
else
throw new JspException(value);
autoFlush = value;
}
public String getAutoFlush() {
return autoFlush;
}
public boolean isAutoFlush() {
return isAutoFlush;
}
/*
* isThreadSafe
*/
public void setIsThreadSafe(String value) throws JspException {
if (value == null)
return;
if ("true".equalsIgnoreCase(value))
isThreadSafe = true;
else if ("false".equalsIgnoreCase(value))
isThreadSafe = false;
else
throw new JspException(value);
isThreadSafeValue = value;
}
public String getIsThreadSafe() {
return isThreadSafeValue;
}
public boolean isThreadSafe() {
return isThreadSafe;
}
/*
* info
*/
public void setInfo(String value) {
info = value;
}
public String getInfo() {
return info;
}
/*
* errorPage
*/
public void setErrorPage(String value) {
errorPage = value;
}
public String getErrorPage() {
return errorPage;
}
/*
* isErrorPage
*/
public void setIsErrorPage(String value) throws JspException {
if (value == null)
return;
if ("true".equalsIgnoreCase(value))
isErrorPage = true;
else if ("false".equalsIgnoreCase(value))
isErrorPage = false;
else
throw new JspException(value);
isErrorPageValue = value;
}
public String getIsErrorPage() {
return isErrorPageValue;
}
public boolean isErrorPage() {
return isErrorPage;
}
/*
* isELIgnored
*/
public void setIsELIgnored(String value) throws JspException {
if (value == null)
return;
if ("true".equalsIgnoreCase(value))
isELIgnored = true;
else if ("false".equalsIgnoreCase(value))
isELIgnored = false;
else {
throw new JspException(value);
}
isELIgnoredValue = value;
}
public void setELIgnored(boolean s) {
isELIgnored = s;
}
public String getIsELIgnored() {
return isELIgnoredValue;
}
public boolean isELIgnored() {
return isELIgnored;
}
// added in NetBeans
public Map<String, TagLibraryInfo> getTagLibraries() {
return taglibsMap;
}
public Map<String, String> getJspPrefixMapper() {
return jspPrefixMapper;
}
public Map getXMLPrefixMapper() {
return xmlPrefixMapper;
}
public Map getApproxXmlPrefixMapper() {
return approxXmlPrefixMapper;
}
public BeanData[] getBeans() {
return beans;
}
public void setBeans(BeanData beans[]) {
this.beans = beans;
}
public boolean isTagFile() {
return this.isTagFile;
}
public void setTagFile(boolean isTagFile) {
this.isTagFile = isTagFile;
}
public TagInfo getTagInfo() {
return this.tagInfo;
}
public void setTagInfo(TagInfo tagInfo) {
this.tagInfo = tagInfo;
}
/** Returns the FunctionMapper for a particular prefix.
* @param currentPrefix relevant tag library prefix. If the expression to evaluate is
* inside an attribute value of a custom tag, then the prefix with which the tag's
* tag library is declared, should be passed in. If the expression is plain
* JSP text, null should be passed in.
* @return FunctionMapper relevant to the given prefix.
*/
//public abstract FunctionMapper getFunctionMapper(String currentPrefix);
public String toString() {
StringBuilder sb = new StringBuilder();
String nl = "\n"; // NOI18N
String indent = " "; // NOI18N
String nlIndent = nl + indent;
sb.append("----- PageInfo -----\n"); // NOI18N
sb.append(indent).append("imports:\n").append(collectionToString(imports, indent + " ")); // NOI18N
sb.append(indent).append("dependants:\n").append(collectionToString(dependants, indent + " ")); // NOI18N
sb.append(indent).append("taglibsMap:\n").append(taglibsMapToString(taglibsMap, indent + " ")); // NOI18N
sb.append(indent).append("prefixMapper:\n").append(mapToString(jspPrefixMapper, indent + " ")); // NOI18N
// PENDING -xmlPrefixMapper
// sb.append(indent).append("xmlprefixMapper:\n").append(mapToString(xmlPrefixMapper, indent + " "));
sb.append(indent).append("approxXmlPrefixMapper :\n").append(mapToString(approxXmlPrefixMapper, indent + " ")); // NOI18N
sb.append(indent).append("language : ").append(language).append('\n'); // NOI18N
sb.append(indent).append("xtends : ").append(xtends).append('\n'); // NOI18N
sb.append(indent).append("contentType : ").append(contentType).append('\n'); // NOI18N
sb.append(indent).append("session : ").append(isSession).append('\n'); // NOI18N
sb.append(indent).append("buffer : ").append(buffer).append('\n'); // NOI18N
sb.append(indent).append("autoFlush : ").append(isAutoFlush).append('\n'); // NOI18N
sb.append(indent).append("threadSafe : ").append(isThreadSafe).append('\n'); // NOI18N
sb.append(indent).append("isErrorPage : ").append(isErrorPage).append('\n'); // NOI18N
sb.append(indent).append("errorPage : ").append(errorPage).append('\n'); // NOI18N
sb.append(indent).append("scriptless : ").append(scriptless).append('\n'); // NOI18N
sb.append(indent).append("scriptingInvalid : ").append(scriptingInvalid).append('\n'); // NOI18N
sb.append(indent).append("elIgnored : ").append(isELIgnored).append('\n'); // NOI18N
sb.append(indent).append("omitXmlDecl : ").append(omitXmlDecl).append('\n'); // NOI18N
sb.append(indent).append("isJspPrefixHijacked : ").append(isJspPrefixHijacked).append('\n'); // NOI18N
sb.append(indent).append("doctypeName : ").append(doctypeName).append('\n'); // NOI18N
sb.append(indent).append("doctypeSystem : ").append(doctypeSystem).append('\n'); // NOI18N
sb.append(indent).append("doctypePublic : ").append(doctypePublic).append('\n'); // NOI18N
sb.append(indent).append("hasJspRoot : ").append(hasJspRoot).append('\n'); // NOI18N
sb.append(indent).append("prefixes:\n").append(collectionToString(new TreeSet<>(prefixes), indent + " ")); // NOI18N
sb.append(indent).append("includePrelude:\n").append(collectionToString(includePrelude, indent + " ")); // NOI18N
sb.append(indent).append("includeCoda:\n").append(collectionToString(includeCoda, indent + " ")); // NOI18N
sb.append(indent).append("pluginDcls:\n").append(collectionToString(pluginDcls, indent + " ")); // NOI18N
sb.append(indent).append("beans:\n").append(beansToString(beans, indent + " ")); // NOI18N
if (isTagFile) {
sb.append(indent).append("Tag file: \n").append(tagInfoToString(tagInfo, indent));
}
return sb.toString();
}
private String collectionToString(Collection c, String indent) { // XXX Arrays.toString() can be sufficient
StringBuilder sb = new StringBuilder();
Iterator it = c.iterator();
while (it.hasNext()) {
sb.append(indent).append(it.next()).append('\n'); // NOI18N
}
return sb.toString();
}
private String taglibsMapToString(Map<String, TagLibraryInfo> m, String indent) {
StringBuilder sb = new StringBuilder();
Iterator<String> it = new TreeSet<>(m.keySet()).iterator();
while (it.hasNext()) {
String key = it.next();
sb.append(indent).append("tag library: ").append(key).append('\n'); // NOI18N
sb.append(tagLibraryInfoToString((TagLibraryInfo)m.get(key), indent + " ")); // NOI18N
}
return sb.toString();
}
public String tagLibraryInfoToString(TagLibraryInfo info, String indent) {
StringBuilder sb = new StringBuilder();
sb.append(indent).append("tlibversion : ").append(getFieldByReflection("tlibversion", info)).append('\n'); // NOI18N
sb.append(indent).append("jspversion : ").append(info.getRequiredVersion()).append('\n'); // NOI18N
sb.append(indent).append("shortname : ").append(info.getShortName()).append('\n'); // NOI18N
sb.append(indent).append("urn : ").append(info.getReliableURN()).append('\n'); // NOI18N
sb.append(indent).append("info : ").append(info.getInfoString()).append('\n'); // NOI18N
sb.append(indent).append("uri : ").append(info.getURI()).append('\n'); // NOI18N
TagInfo tags[] = info.getTags();
if (tags != null) {
for (int i = 0; i < tags.length; i++)
sb.append(tagInfoToString(tags[i], indent + " ")); // NOI18N
}
TagFileInfo tagFiles[] = info.getTagFiles().clone();
Arrays.sort(tagFiles, TAG_FILE_INFO_COMPARATOR);
if (tagFiles != null) {
for (int i = 0; i < tagFiles.length; i++)
sb.append(tagFileToString(tagFiles[i], indent + " ")); // NOI18N
}
FunctionInfo functions[] = info.getFunctions();
if (functions != null) {
for (int i = 0; i < functions.length; i++)
sb.append(functionInfoToString(functions[i], indent + " ")); // NOI18N
}
return sb.toString();
}
public String tagInfoToString(TagInfo tag, String indent) {
StringBuilder sb = new StringBuilder();
if (tag != null) {
sb.append(indent).append("tag name : ").append(tag.getTagName()).append('\n'); // NOI18N
sb.append(indent).append(" class : ").append(tag.getTagClassName()).append('\n'); // NOI18N
sb.append(indent).append(" attribs : ["); // NOI18N
TagAttributeInfo attrs[] = tag.getAttributes();
for (int i = 0; i < attrs.length; i++) {
sb.append(attrs[i].getName());
if (i < attrs.length - 1) {
sb.append(", "); // NOI18N
}
}
sb.append("]\n"); // NOI18N
}
else {
sb.append(indent).append("taginfo is null\n"); // NOI18N
}
return sb.toString();
}
public String functionInfoToString(FunctionInfo function, String indent) {
StringBuilder sb = new StringBuilder();
if (function != null) {
sb.append(indent).append("function name : ").append(function.getName()).append('\n'); // NOI18N
sb.append(indent).append(" class : ").append(function.getFunctionClass()).append('\n'); // NOI18N
sb.append(indent).append(" signature: ").append(function.getFunctionSignature()).append('\n'); // NOI18N
}
else {
sb.append(indent).append("functioninfo is null\n"); // NOI18N
}
return sb.toString();
}
public String tagFileToString(TagFileInfo tagFile, String indent) {
StringBuilder sb = new StringBuilder();
sb.append(indent).append("tagfile path : ").append(tagFile.getPath()).append('\n'); // NOI18N
sb.append(tagInfoToString(tagFile.getTagInfo(), indent));
return sb.toString();
}
private Object getFieldByReflection(String fieldName, TagLibraryInfo info) {
try {
java.lang.reflect.Field f = TagLibraryInfo.class.getDeclaredField(fieldName);
f.setAccessible(true);
return f.get(info);
}
catch (NoSuchFieldException e) {
Logger.getLogger("global").log(Level.INFO, null, e);
}
catch (IllegalAccessException e) {
Logger.getLogger("global").log(Level.INFO, null, e);
}
return null;
}
private String beansToString(BeanData beans[], String indent) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < beans.length; i++) {
sb.append(indent).append("bean : ").append(beans[i].getId()).append(", "). // NOI18N
// append(scopeToString(beans[i].getScope())).append(", "). // NOI18N
append(beans[i].getClassName()).append('\n'); // NOI18N
}
return sb.toString();
}
// private String scopeToString(int scope) {
// switch (scope) {
// case PageContext.PAGE_SCOPE : return "PAGE"; // NOI18N
// case PageContext.SESSION_SCOPE : return "SESSION"; // NOI18N
// case PageContext.APPLICATION_SCOPE : return "APPLICATION"; // NOI18N
// case PageContext.REQUEST_SCOPE : return "REQUEST"; // NOI18N
// }
// return " !!! ";
// }
/** Interface which describes data for beans used by this page. */
public interface BeanData {
/** Identifier of the bean in the page (variable name). */
public String getId();
/** Returns the class name for this bean. */
public String getClassName();
} // interface BeanData
// helper methods for help implement toString()
private static String mapToString(Map<String, String> m, String indent) {
StringBuilder sb = new StringBuilder();
Iterator<String> it = new TreeSet<>(m.keySet()).iterator();
while (it.hasNext()) {
String key = it.next();
sb.append(indent).append(key).append(" -> ").append(m.get(key)).append('\n');
}
return sb.toString();
}
}