/* * #%L * ACS AEM Tools Bundle * %% * Copyright (C) 2013 Adobe * %% * Licensed 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. * #L% */ package com.adobe.acs.tools.jsp_code_display.impl; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.ServletException; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.sling.SlingServlet; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.SlingHttpServletResponse; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.servlets.SlingAllMethodsServlet; import org.apache.sling.commons.json.JSONException; import org.apache.sling.commons.json.JSONObject; import org.apache.sling.settings.SlingSettingsService; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.service.component.ComponentContext; @SuppressWarnings("serial") @SlingServlet(resourceTypes = "acs-tools/components/jsp-code-display", extensions = "json", methods = "POST", selectors = "fetch") public class JspCodeServlet extends SlingAllMethodsServlet { @Reference private SlingSettingsService slingSettingsService; private File fileRoot; @Override protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException { try { JSONObject result = new JSONObject(); String line = request.getParameter("line"); if (StringUtils.isNotBlank(line)) { Pattern pattern = Pattern.compile("^(.+)\\.(\\w+)\\.(\\w+)\\((\\w+\\.java):(\\d+)\\)$"); Matcher matcher = pattern.matcher(line); if (matcher.matches()) { String packageName = matcher.group(1); String fileName = matcher.group(4); String lineNumber = matcher.group(5); String sourceFilePath = "/" + packageName.replace('.', '/') + "/" + fileName; InputStream instream = null; if (fileRoot != null) { // we are on 6.1 or otherwise using the fs classloader File classFile = new File(fileRoot, sourceFilePath); if (classFile.exists()) { instream = new FileInputStream(classFile); } } else { ResourceResolver resourceResolver = request.getResourceResolver(); Resource classesRoot = resourceResolver.getResource("/var/classes"); if (classesRoot != null) { if (classesRoot.getChild("org") != null) { // assume this is 5.6.1 or before Resource fileResource = resourceResolver.getResource(classesRoot.getPath() + sourceFilePath); if (fileResource != null) { instream = fileResource.adaptTo(InputStream.class); } } else { // assume this is 6.0, so take the first child node and try underneath that Iterator<Resource> roots = classesRoot.listChildren(); if (roots.hasNext()) { Resource fileResource = resourceResolver.getResource(roots.next().getPath() + sourceFilePath); if (fileResource != null) { instream = fileResource.adaptTo(InputStream.class); } } } } } if (instream != null) { result.put("success", true); result.put("lineNumber", Integer.parseInt(lineNumber)); result.put("code", IOUtils.toString(instream, "UTF-8")); IOUtils.closeQuietly(instream); } else { result.put("success", false); result.put("error", "Compiled JSP could not be found."); } } } else { result.put("success", false); result.put("error", "No line was provided"); } response.setContentType("application/json"); result.write(response.getWriter()); } catch (JSONException e) { throw new ServletException(e); } } @Activate protected void activate(ComponentContext ctx) { BundleContext bundleContext = ctx.getBundleContext(); // this is less than ideal, but there's no better way to get to the fs classloader's data directory for (Bundle bundle : bundleContext.getBundles()) { if (bundle.getSymbolicName().equals("org.apache.sling.commons.fsclassloader")) { this.fileRoot = new File(slingSettingsService.getSlingHomePath(), "launchpad/felix/bundle"+bundle.getBundleId()+"/data/classes"); break; } } } }