blob: b33986652a3a952f0afade9c8bce26d5ce54e10c [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.profiler.j2ee;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.lib.profiler.client.ClientUtils;
import org.netbeans.lib.profiler.common.Profiler;
import org.netbeans.modules.j2ee.deployment.devmodules.api.JSPServletFinder;
import org.netbeans.modules.j2ee.spi.ejbjar.EarProvider;
import org.netbeans.modules.profiler.nbimpl.project.ProjectUtilities;
import org.netbeans.modules.web.api.webmodule.WebModule;
import org.netbeans.modules.web.api.webmodule.WebProjectConstants;
import org.openide.ErrorManager;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.NbBundle;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.text.MessageFormat;
import java.util.*;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.netbeans.modules.profiler.api.java.JavaProfilerSource;
import org.openide.util.Lookup;
/**
*
* @author Jiri Sedlacek
*/
@NbBundle.Messages({
"WebProjectUtils_CannotFindServletMsg=Cannot resolve servlet class generated from {0}. It will not be included into root methods.",
"WebProjectUtils_CannotFindServletClassMsg=Cannot find servlet class {0} defined in deployment descriptor. Its methods will not be included into root methods.",
"WebProjectUtils_CannotFindFilterClassMsg=Cannot find filter class {0} defined in deployment descriptor. Its methods will not be included into root methods.",
"WebProjectUtils_CannotFindListenerClassMsg=Cannot find listener class {0} defined in deployment descriptor. Its methods will not be included into root methods."
})
public class WebProjectUtils {
//~ Static fields/initializers -----------------------------------------------------------------------------------------------
private static final Logger LOGGER = Logger.getLogger(WebProjectUtils.class.getName());
private static final Map<ClientUtils.SourceCodeSelection, String> jspClass2NameMap = new HashMap<ClientUtils.SourceCodeSelection, String>();
private static final String[][] jspServletMethods = new String[][] {
{
"_jspService",
"(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V"
}
};
//~ Methods ------------------------------------------------------------------------------------------------------------------
public static Document getDeploymentDescriptorDocument(FileObject deploymentDescriptorFile) {
Document deploymentDescriptorDocument = null;
try {
DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
dbfactory.setValidating(false);
DocumentBuilder builder = dbfactory.newDocumentBuilder();
builder.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
StringReader reader = new StringReader("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); // NOI18N
InputSource source = new InputSource(reader);
source.setPublicId(publicId);
source.setSystemId(systemId);
return source;
}
});
deploymentDescriptorDocument = builder.parse(FileUtil.toFile(deploymentDescriptorFile));
} catch (Exception e) {
e.printStackTrace();
}
return deploymentDescriptorDocument;
}
public static Collection<Document> getDeploymentDescriptorDocuments(Project project, boolean subprojects) {
Collection<Document> documents = new ArrayList<Document>();
for (FileObject ddFile : getDeploymentDescriptorFileObjects(project, subprojects)) {
Document d = getDeploymentDescriptorDocument(ddFile);
if (d != null) documents.add(d);
}
return documents;
}
public static Collection<FileObject> getDeploymentDescriptorFileObjects(Project project, boolean subprojects) {
Collection<FileObject> descriptors = new ArrayList<FileObject>();
for (WebModule wm : getWebModules(project, subprojects)) {
FileObject d = wm.getDeploymentDescriptor();
if (d != null) descriptors.add(d);
}
return descriptors;
}
public static Collection<FileObject> getDocumentBaseFileObjects(Project project, boolean subprojects) {
Collection<FileObject> basefos = new ArrayList<FileObject>();
for (WebModule wm : getWebModules(project, subprojects)) {
FileObject d = wm.getDocumentBase();
if (d != null) basefos.add(d);
}
return basefos;
}
public static Collection<File> getDocumentBaseFiles(Project project, boolean subprojects) {
Collection<File> basefiles = new ArrayList<File>();
for (FileObject basefo : getDocumentBaseFileObjects(project, subprojects)) {
basefiles.add(FileUtil.toFile(basefo));
}
return basefiles;
}
public static boolean isWebProject(Lookup.Provider p) {
assert p != null;
return p.getLookup().lookup(WebModule.class) != null;
}
public static ArrayList[] getFilterClasses(Document deploymentDescriptorDocument) {
ArrayList mappedFilters = new ArrayList();
ArrayList notMappedFilters = new ArrayList();
NodeList filtersList = getFilters(deploymentDescriptorDocument);
NodeList filterMappingsList = getFilterMappings(deploymentDescriptorDocument);
Collection<String> mappedFilterNames = new HashSet<String>();
for (int i = 0; i < filterMappingsList.getLength(); i++) {
String mappedFilterName = getElementContent((Element) filterMappingsList.item(i), "filter-name"); // NOI18N
if ((mappedFilterName != null) && !mappedFilterNames.contains(mappedFilterName)) {
mappedFilterNames.add(mappedFilterName);
}
}
for (int i = 0; i < filtersList.getLength(); i++) {
String filterName = getElementContent((Element) filtersList.item(i), "filter-name"); // NOI18N
String filterClassName = getElementContent((Element) filtersList.item(i), "filter-class"); // NOI18N
if ((filterName != null) && (filterClassName != null) && mappedFilterNames.contains(filterName)) {
if (!mappedFilters.contains(filterClassName)) {
mappedFilters.add(filterClassName);
}
} else {
if (!notMappedFilters.contains(filterClassName)) {
notMappedFilters.add(filterClassName);
}
}
}
return new ArrayList[] { mappedFilters, notMappedFilters };
}
public static NodeList getFilterMappings(Document deploymentDescriptorDocument) {
return deploymentDescriptorDocument.getElementsByTagName("filter-mapping"); // NOI18N
}
public static NodeList getFilters(Document deploymentDescriptorDocument) {
return deploymentDescriptorDocument.getElementsByTagName("filter"); // NOI18N
}
public static boolean isHttpServlet(FileObject fo) {
// FIXME pass in the JavaProfilerSource instead
JavaProfilerSource src = JavaProfilerSource.createFrom(fo);
return src != null && src.isInstanceOf("javax.servlet.http.HttpServlet"); // NOI18N
}
public static boolean isJSP(FileObject fo) {
return "jsp".equals(fo.getExt()); // NOI18N
}
public static String getJSPFileContext(Project project, FileObject jspFile, boolean subprojects) {
Collection<FileObject> docBases = getDocumentBaseFileObjects(project, subprojects);
String relPathUsed = null;
for (FileObject docBase : docBases) {
if (docBase == null) {
continue;
}
String relativePath = FileUtil.getRelativePath(docBase, jspFile);
if (relativePath == null) {
continue;
}
if ((relPathUsed == null) || (relPathUsed.length() > relativePath.length())) {
relPathUsed = relativePath;
}
}
return relPathUsed;
}
public static ClientUtils.SourceCodeSelection getJSPFileRootMethod(Project project, FileObject jspFile) {
return getJSPMethodSignature(project, jspFile);
}
public static ClientUtils.SourceCodeSelection getJSPMethodSignature(Project project, FileObject jspFile) {
String jspPseudoServletClass = getJSPPseudoServletClass(project, jspFile);
if (jspPseudoServletClass == null) {
LOGGER.log(Level.WARNING, Bundle.WebProjectUtils_CannotFindServletMsg(FileUtil.toFile(jspFile).getPath()));
return null; // According to Issue 62519, jsp file is not resolved/found due odd project layout
}
return getJSPMethodSignature(jspPseudoServletClass);
}
public static ClientUtils.SourceCodeSelection getJSPMethodSignature(String jspPseudoServletClass) {
return new ClientUtils.SourceCodeSelection(jspPseudoServletClass, jspServletMethods[0][0], jspServletMethods[0][1]);
}
public static Set<ClientUtils.SourceCodeSelection> getJSPMethodSignatures(Project project, boolean subprojects) {
Set<ClientUtils.SourceCodeSelection> methodSignatures = new HashSet<ClientUtils.SourceCodeSelection>();
Collection<FileObject> baseFOs = getDocumentBaseFileObjects(project, subprojects);
if ((baseFOs == null) || baseFOs.isEmpty()) {
return methodSignatures;
}
for (FileObject baseFO : baseFOs) {
int jspStringStartIndex = baseFO.getPath().length();
List<FileObject> jspFileObjects = getJSPs(baseFO);
ClientUtils.SourceCodeSelection methodDescription;
for (FileObject jsp : jspFileObjects) {
methodDescription = getJSPMethodSignature(project, jsp);
if (methodDescription != null) {
// TODO: Get rid of this ridiculous formatter and enhance FlatProfileContainer to return a SourceCodeSelection of a certain row
jspClass2NameMap.put(methodDescription, jsp.getPath().substring(jspStringStartIndex));
// ****
methodSignatures.add(methodDescription);
}
}
}
return methodSignatures;
}
public static String getJSPPath(ClientUtils.SourceCodeSelection jspMethod) {
return jspClass2NameMap.get(jspMethod);
}
public static String getJSPPseudoServletClass(Project project, FileObject jspFile) {
String jspPseudoServletJavaFile = JSPServletFinder.findJSPServletFinder(jspFile)
.getServletResourcePath(getJSPFileContext(project, jspFile, true));
if (jspPseudoServletJavaFile == null) {
return null; // According to Issue 62519, jsp file is not resolved/found due odd project layout
}
String jspPseudoServletJavaClass = jspPseudoServletJavaFile.substring(0,
jspPseudoServletJavaFile.length()
- ".java".length()).replace('/', '.'); // NOI18N
return jspPseudoServletJavaClass;
}
public static ClientUtils.SourceCodeSelection[] getJSPRootMethods(Project project, boolean subprojects) {
Set<ClientUtils.SourceCodeSelection> jspRootMethodDescriptions = getJSPMethodSignatures(project, subprojects);
if (jspRootMethodDescriptions == null) {
return new ClientUtils.SourceCodeSelection[0];
}
return jspRootMethodDescriptions.toArray(new ClientUtils.SourceCodeSelection[0]);
}
public static ArrayList getJSPs(FileObject documentBase) {
ArrayList jspFileObjects = new ArrayList();
if (documentBase.isFolder()) {
searchForJSPs(documentBase, jspFileObjects);
}
return jspFileObjects;
}
public static ArrayList getListenerClasses(Document deploymentDescriptorDocument) {
ArrayList listeners = new ArrayList();
NodeList listenersList = getListeners(deploymentDescriptorDocument);
for (int i = 0; i < listenersList.getLength(); i++) {
String listenerClass = getElementContent((Element) listenersList.item(i), "listener-class"); // NOI18N
if ((listenerClass != null) && !listeners.contains(listenerClass)) {
listeners.add(listenerClass);
}
}
return listeners;
}
public static NodeList getListeners(Document deploymentDescriptorDocument) {
return deploymentDescriptorDocument.getElementsByTagName("listener"); // NOI18N
}
public static boolean isMappedServlet(FileObject servlet, Project project, boolean subprojects) {
Collection<Document> dds = getDeploymentDescriptorDocuments(project, subprojects);
for (Document dd : dds) {
if (getServletMapping(servlet, dd) != null) {
return true;
}
}
return false;
}
public static ArrayList[] getServletClasses(Document deploymentDescriptorDocument) {
ArrayList mappedServlets = new ArrayList();
ArrayList notMappedServlets = new ArrayList();
NodeList servletsList = getServlets(deploymentDescriptorDocument);
NodeList servletMappingsList = getServletMappings(deploymentDescriptorDocument);
Collection<String> mappedServletNames = new HashSet<String>();
for (int i = 0; i < servletMappingsList.getLength(); i++) {
String mappedServletName = getElementContent((Element) servletMappingsList.item(i), "servlet-name"); // NOI18N
if ((mappedServletName != null) && !mappedServletNames.contains(mappedServletName)) {
mappedServletNames.add(mappedServletName);
}
}
for (int i = 0; i < servletsList.getLength(); i++) {
String servletName = getElementContent((Element) servletsList.item(i), "servlet-name"); // NOI18N
String servletClassName = getElementContent((Element) servletsList.item(i), "servlet-class"); // NOI18N
if ((servletName != null) && (servletClassName != null) && mappedServletNames.contains(servletName)) {
if (!mappedServlets.contains(servletClassName)) {
mappedServlets.add(servletClassName);
}
} else {
if (!notMappedServlets.contains(servletClassName)) {
notMappedServlets.add(servletClassName);
}
}
}
return new ArrayList[] { mappedServlets, notMappedServlets };
}
public static String getServletMapping(FileObject servletFO, Document deploymentDescriptorDocument) {
// FIXME - pass in JavaProfilerSource param
JavaProfilerSource src = JavaProfilerSource.createFrom(servletFO);
if (src == null) {
return null;
}
String servletClassName = src.getTopLevelClass().getVMName();
if ((servletClassName == null) || (deploymentDescriptorDocument == null)) {
return null;
}
NodeList servletsList = getServlets(deploymentDescriptorDocument);
for (int i = 0; i < servletsList.getLength(); i++) {
String servletName = getElementContent((Element) servletsList.item(i), "servlet-name"); // NOI18N
String className = getElementContent((Element) servletsList.item(i), "servlet-class"); // NOI18N
if ((servletName != null) && (className != null) && servletClassName.equals(className)) {
NodeList servletMappingsList = getServletMappings(deploymentDescriptorDocument);
for (int j = 0; j < servletMappingsList.getLength(); j++) {
if (servletName.equals(getElementContent((Element) servletMappingsList.item(j), "servlet-name"))) {
// NOI18N
return getElementContent((Element) servletMappingsList.item(j), "url-pattern"); // NOI18N
}
}
return null;
}
}
return null;
}
public static NodeList getServletMappings(Document deploymentDescriptorDocument) {
return deploymentDescriptorDocument.getElementsByTagName("servlet-mapping"); // NOI18N
}
public static NodeList getServlets(Document deploymentDescriptorDocument) {
return deploymentDescriptorDocument.getElementsByTagName("servlet"); // NOI18N
}
// returns true if passed fo lives in /web directory
public static boolean isWebDocumentSource(FileObject fo, Project project) {
SourceGroup[] sg = ProjectUtils.getSources(project).getSourceGroups(WebProjectConstants.TYPE_DOC_ROOT);
for (int i = 0; i < sg.length; i++) {
if (FileUtil.isParentOf(sg[i].getRootFolder(), fo)) {
return true;
}
}
return false;
}
// returns true if passed fo lives in /src directory
public static boolean isWebJavaSource(FileObject fo, Project project) {
SourceGroup[] sg = ProjectUtils.getSources(project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
for (int i = 0; i < sg.length; i++) {
if (FileUtil.isParentOf(sg[i].getRootFolder(), fo)) {
return true;
}
}
return false;
}
public static Collection<WebModule> getWebModules(Project project, boolean subprojects) {
Collection<WebModule> wms = new ArrayList<WebModule>();
WebModule wm = WebModule.getWebModule(project.getProjectDirectory());
if (wm != null) {
wms.add(wm);
}
if (subprojects) {
EarProvider earprovider = project.getLookup().lookup(EarProvider.class);
if ((wm == null) && (earprovider != null)) {
Set<Project> projects = new HashSet<Project>();
ProjectUtilities.fetchSubprojects(project, projects);
for (Project subp : projects) {
wms.addAll(getWebModules(subp, subprojects));
}
}
}
return wms;
}
public static void resetJSPNameCache() {
jspClass2NameMap.clear();
}
private static String getElementContent(Element rootElement, String tagName) {
if (rootElement == null) {
return null;
}
NodeList elementsList = rootElement.getElementsByTagName(tagName);
if ((elementsList == null) || (elementsList.getLength() == 0)) {
return null;
}
Node element = elementsList.item(0);
if (element == null) {
return null;
}
String elementContents = element.getTextContent();
if (elementContents == null) {
return null;
}
return elementContents.trim();
}
private static void searchForJSPs(FileObject root, ArrayList jspFileObjects) {
FileObject[] childs = root.getChildren();
FileObject child;
for (int i = 0; i < childs.length; i++) {
child = childs[i];
if (child.isFolder()) {
searchForJSPs(child, jspFileObjects);
} else if (child.isData() && "jsp".equals(child.getExt())) {
jspFileObjects.add(child); // NOI18N
}
}
}
}