Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * 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.apache.jasper.compiler;
 
 import java.io.File;
 import java.util.Map;
 
Contains static utilities for generating SMAP data based on the current version of Jasper.

Author(s):
Jayson Falkner
Shawn Bayern
Robert Field (inner SDEInstaller class)
Mark Roth
Kin-man Chung
 
 public class SmapUtil {
 
     //*********************************************************************
     // Constants
 
     public static final String SMAP_ENCODING = "UTF-8";
 
     //*********************************************************************
     // Public entry points
 
    
Generates an appropriate SMAP representing the current compilation context. (JSR-045.)

Parameters:
ctxt Current compilation context
pageNodes The current JSP page
Returns:
a SMAP for the page
 
     public static String[] generateSmap(
         JspCompilationContext ctxt,
         Node.Nodes pageNodes)
         throws IOException {
 
         // Scan the nodes for presence of Jasper generated inner classes
         PreScanVisitor psVisitor = new PreScanVisitor();
         try {
             pageNodes.visit(psVisitor);
         } catch (JasperException ex) {
         }
         HashMap map = psVisitor.getMap();
 
         // set up our SMAP generator
         SmapGenerator g = new SmapGenerator();
        
        
Disable reading of input SMAP because: 1. There is a bug here: getRealPath() is null if .jsp is in a jar Bugzilla 14660. 2. Mappings from other sources into .jsp files are not supported. TODO: fix 1. if 2. is not true. // determine if we have an input SMAP String smapPath = inputSmapPath(ctxt.getRealPath(ctxt.getJspFile())); File inputSmap = new File(smapPath); if (inputSmap.exists()) { byte[] embeddedSmap = null; byte[] subSmap = SDEInstaller.readWhole(inputSmap); String subSmapString = new String(subSmap, SMAP_ENCODING); g.addSmap(subSmapString, "JSP"); }
 
 
         // now, assemble info about our own stratum (JSP) using JspLineMap
         SmapStratum s = new SmapStratum("JSP");
 
 
        // Map out Node.Nodes
        evaluateNodes(pageNodessmapctxt.getOptions().getMappedFile());
        s.optimizeLineSection();
        g.addStratum(strue);
        if (ctxt.getOptions().isSmapDumped()) {
            File outSmap = new File(ctxt.getClassFileName() + ".smap");
            PrintWriter so =
                new PrintWriter(
                    new OutputStreamWriter(
                        new FileOutputStream(outSmap),
                        ));
            so.print(g.getString());
            so.close();
        }
        String classFileName = ctxt.getClassFileName();
        int innerClassCount = map.size();
        String [] smapInfo = new String[2 + innerClassCount*2];
        smapInfo[0] = classFileName;
        smapInfo[1] = g.getString();
        int count = 2;
        Iterator iter = map.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entryiter.next();
            String innerClass = (Stringentry.getKey();
            s = (SmapStratumentry.getValue();
            s.optimizeLineSection();
            g = new SmapGenerator();
            g.setOutputFileName(unqualify(ctxt.getServletJavaFileName()));
            g.addStratum(strue);
            String innerClassFileName =
                classFileName.substring(0, classFileName.indexOf(".class")) +
                '$' + innerClass + ".class";
            if (ctxt.getOptions().isSmapDumped()) {
                File outSmap = new File(innerClassFileName + ".smap");
                PrintWriter so =
                    new PrintWriter(
                        new OutputStreamWriter(
                            new FileOutputStream(outSmap),
                            ));
                so.print(g.getString());
                so.close();
            }
            smapInfo[count] = innerClassFileName;
            smapInfo[count+1] = g.getString();
            count += 2;
        }
        return smapInfo;
    }
    public static void installSmap(String[] smap)
        throws IOException {
        if (smap == null) {
            return;
        }
        for (int i = 0; i < smap.lengthi += 2) {
            File outServlet = new File(smap[i]);
            SDEInstaller.install(outServletsmap[i+1].getBytes());
        }
    }
    //*********************************************************************
    // Private utilities

    
Returns an unqualified version of the given file path.
    private static String unqualify(String path) {
        path = path.replace('\\''/');
        return path.substring(path.lastIndexOf('/') + 1);
    }

    
Returns a file path corresponding to a potential SMAP input for the given compilation input (JSP file).
    private static String inputSmapPath(String path) {
        return path.substring(0, path.lastIndexOf('.') + 1) + "smap";
    }
    //*********************************************************************
    // Installation logic (from Robert Field, JSR-045 spec lead)
    private static class SDEInstaller {
        private org.jboss.logging.Logger log=
            org.jboss.logging.Logger.getLoggerSDEInstaller.class );
        static final String nameSDE = "SourceDebugExtension";
        byte[] orig;
        byte[] sdeAttr;
        byte[] gen;
        int origPos = 0;
        int genPos = 0;
        int sdeIndex;
        public static void main(String[] argsthrows IOException {
            if (args.length == 2) {
                install(new File(args[0]), new File(args[1]));
            } else if (args.length == 3) {
                install(
                    new File(args[0]),
                    new File(args[1]),
                    new File(args[2]));
            } else {
                ..println(
                    "Usage: <command> <input class file> "
                        + "<attribute file> <output class file name>\n"
                        + "<command> <input/output class file> <attribute file>");
            }
        }
        static void install(File inClassFileFile attrFileFile outClassFile)
            throws IOException {
            new SDEInstaller(inClassFileattrFileoutClassFile);
        }
        static void install(File inOutClassFileFile attrFile)
            throws IOException {
            File tmpFile = new File(inOutClassFile.getPath() + "tmp");
            new SDEInstaller(inOutClassFileattrFiletmpFile);
            if (!inOutClassFile.delete()) {
                throw new IOException("inOutClassFile.delete() failed");
            }
            if (!tmpFile.renameTo(inOutClassFile)) {
                throw new IOException("tmpFile.renameTo(inOutClassFile) failed");
            }
        }
        static void install(File classFilebyte[] smapthrows IOException {
            File tmpFile = new File(classFile.getPath() + "tmp");
            new SDEInstaller(classFilesmaptmpFile);
            if (!classFile.delete()) {
                throw new IOException("classFile.delete() failed");
            }
            if (!tmpFile.renameTo(classFile)) {
                throw new IOException("tmpFile.renameTo(classFile) failed");
            }
        }
        SDEInstaller(File inClassFilebyte[] sdeAttrFile outClassFile)
            throws IOException {
            if (!inClassFile.exists()) {
                throw new FileNotFoundException("no such file: " + inClassFile);
            }
            this. = sdeAttr;
            // get the bytes
             = readWhole(inClassFile);
             = new byte[. + sdeAttr.length + 100];
            // do it
            addSDE();
            // write result
            FileOutputStream outStream = new FileOutputStream(outClassFile);
            outStream.write(, 0, );
            outStream.close();
        }
        SDEInstaller(File inClassFileFile attrFileFile outClassFile)
            throws IOException {
            this(inClassFilereadWhole(attrFile), outClassFile);
        }
        static byte[] readWhole(File inputthrows IOException {
            FileInputStream inStream = new FileInputStream(input);
            int len = (int)input.length();
            byte[] bytes = new byte[len];
            if (inStream.read(bytes, 0, len) != len) {
                throw new IOException("expected size: " + len);
            }
            inStream.close();
            return bytes;
        }
        void addSDE() throws UnsupportedEncodingExceptionIOException {
            int i;
            copy(4 + 2 + 2); // magic min/maj version
            int constantPoolCountPos = ;
            int constantPoolCount = readU2();
            if (.isDebugEnabled())
                .debug("constant pool count: " + constantPoolCount);
            writeU2(constantPoolCount);
            // copy old constant pool return index of SDE symbol, if found
             = copyConstantPool(constantPoolCount);
            if ( < 0) {
                // if "SourceDebugExtension" symbol not there add it
                writeUtf8ForSDE();
                // increment the countantPoolCount
                 = constantPoolCount;
                ++constantPoolCount;
                randomAccessWriteU2(constantPoolCountPosconstantPoolCount);
                if (.isDebugEnabled())
                    .debug("SourceDebugExtension not found, installed at: " + );
            } else {
                if (.isDebugEnabled())
                    .debug("SourceDebugExtension found at: " + );
            }
            copy(2 + 2 + 2); // access, this, super
            int interfaceCount = readU2();
            writeU2(interfaceCount);
            if (.isDebugEnabled())
                .debug("interfaceCount: " + interfaceCount);
            copy(interfaceCount * 2);
            copyMembers(); // fields
            copyMembers(); // methods
            int attrCountPos = ;
            int attrCount = readU2();
            writeU2(attrCount);
            if (.isDebugEnabled())
                .debug("class attrCount: " + attrCount);
            // copy the class attributes, return true if SDE attr found (not copied)
            if (!copyAttrs(attrCount)) {
                // we will be adding SDE and it isn't already counted
                ++attrCount;
                randomAccessWriteU2(attrCountPosattrCount);
                if (.isDebugEnabled())
                    .debug("class attrCount incremented");
            }
            writeAttrForSDE();
        }
        void copyMembers() {
            int count = readU2();
            writeU2(count);
            if (.isDebugEnabled())
                .debug("members count: " + count);
            for (int i = 0; i < count; ++i) {
                copy(6); // access, name, descriptor
                int attrCount = readU2();
                writeU2(attrCount);
                if (.isDebugEnabled())
                    .debug("member attr count: " + attrCount);
                copyAttrs(attrCount);
            }
        }
        boolean copyAttrs(int attrCount) {
            boolean sdeFound = false;
            for (int i = 0; i < attrCount; ++i) {
                int nameIndex = readU2();
                // don't write old SDE
                if (nameIndex == ) {
                    sdeFound = true;
                    if (.isDebugEnabled())
                        .debug("SDE attr found");
                } else {
                    writeU2(nameIndex); // name
                    int len = readU4();
                    writeU4(len);
                    copy(len);
                    if (.isDebugEnabled())
                        .debug("attr len: " + len);
                }
            }
            return sdeFound;
        }
        void writeAttrForSDE(int index) {
            writeU2(index);
            writeU4(.);
            for (int i = 0; i < .; ++i) {
                writeU1([i]);
            }
        }
        void randomAccessWriteU2(int posint val) {
            int savePos = ;
             = pos;
            writeU2(val);
             = savePos;
        }
        int readU1() {
            return ((int)[++]) & 0xFF;
        }
        int readU2() {
            int res = readU1();
            return (res << 8) + readU1();
        }
        int readU4() {
            int res = readU2();
            return (res << 16) + readU2();
        }
        void writeU1(int val) {
            [++] = (byte)val;
        }
        void writeU2(int val) {
            writeU1(val >> 8);
            writeU1(val & 0xFF);
        }
        void writeU4(int val) {
            writeU2(val >> 16);
            writeU2(val & 0xFFFF);
        }
        void copy(int count) {
            for (int i = 0; i < count; ++i) {
                [++] = [++];
            }
        }
        byte[] readBytes(int count) {
            byte[] bytes = new byte[count];
            for (int i = 0; i < count; ++i) {
                bytes[i] = [++];
            }
            return bytes;
        }
        void writeBytes(byte[] bytes) {
            for (int i = 0; i < bytes.length; ++i) {
                [++] = bytes[i];
            }
        }
        int copyConstantPool(int constantPoolCount)
            throws UnsupportedEncodingExceptionIOException {
            int sdeIndex = -1;
            // copy const pool index zero not in class file
            for (int i = 1; i < constantPoolCount; ++i) {
                int tag = readU1();
                writeU1(tag);
                switch (tag) {
                    case 7 : // Class
                    case 8 : // String
                        if (.isDebugEnabled())
                            .debug(i + " copying 2 bytes");
                        copy(2);
                        break;
                    case 9 : // Field
                    case 10 : // Method
                    case 11 : // InterfaceMethod
                    case 3 : // Integer
                    case 4 : // Float
                    case 12 : // NameAndType
                        if (.isDebugEnabled())
                            .debug(i + " copying 4 bytes");
                        copy(4);
                        break;
                    case 5 : // Long
                    case 6 : // Double
                        if (.isDebugEnabled())
                            .debug(i + " copying 8 bytes");
                        copy(8);
                        i++;
                        break;
                    case 1 : // Utf8
                        int len = readU2();
                        writeU2(len);
                        byte[] utf8 = readBytes(len);
                        String str = new String(utf8"UTF-8");
                        if (.isDebugEnabled())
                            .debug(i + " read class attr -- '" + str + "'");
                        if (str.equals()) {
                            sdeIndex = i;
                        }
                        writeBytes(utf8);
                        break;
                    default :
                        throw new IOException("unexpected tag: " + tag);
                }
            }
            return sdeIndex;
        }
        void writeUtf8ForSDE() {
            int len = .length();
            writeU1(1); // Utf8 tag
            writeU2(len);
            for (int i = 0; i < len; ++i) {
                writeU1(.charAt(i));
            }
        }
    }
    public static void evaluateNodes(
        Node.Nodes nodes,
        SmapStratum s,
        HashMap innerClassMap,
        boolean breakAtLF) {
        try {
            nodes.visit(new SmapGenVisitor(sbreakAtLFinnerClassMap));
        } catch (JasperException ex) {
        }
    }
    static class SmapGenVisitor extends Node.Visitor {
        private SmapStratum smap;
        private boolean breakAtLF;
        private HashMap innerClassMap;
        SmapGenVisitor(SmapStratum sboolean breakAtLFHashMap map) {
            this. = s;
            this. = breakAtLF;
            this. = map;
        }
        public void visitBody(Node nthrows JasperException {
            SmapStratum smapSave = ;
            String innerClass = n.getInnerClassName();
            if (innerClass != null) {
                this. = (SmapStratum.get(innerClass);
            }
            super.visitBody(n);
             = smapSave;
        }
        public void visit(Node.Declaration nthrows JasperException {
            doSmapText(n);
        }
        public void visit(Node.Expression nthrows JasperException {
            doSmapText(n);
        }
        public void visit(Node.Scriptlet nthrows JasperException {
            doSmapText(n);
        }
        public void visit(Node.IncludeAction nthrows JasperException {
            doSmap(n);
            visitBody(n);
        }
        public void visit(Node.ForwardAction nthrows JasperException {
            doSmap(n);
            visitBody(n);
        }
        public void visit(Node.GetProperty nthrows JasperException {
            doSmap(n);
            visitBody(n);
        }
        public void visit(Node.SetProperty nthrows JasperException {
            doSmap(n);
            visitBody(n);
        }
        public void visit(Node.UseBean nthrows JasperException {
            doSmap(n);
            visitBody(n);
        }
        public void visit(Node.PlugIn nthrows JasperException {
            doSmap(n);
            visitBody(n);
        }
        public void visit(Node.CustomTag nthrows JasperException {
            doSmap(n);
            visitBody(n);
        }
        public void visit(Node.UninterpretedTag nthrows JasperException {
            doSmap(n);
            visitBody(n);
        }
        public void visit(Node.JspElement nthrows JasperException {
            doSmap(n);
            visitBody(n);
        }
        public void visit(Node.JspText nthrows JasperException {
            doSmap(n);
            visitBody(n);
        }
        public void visit(Node.NamedAttribute nthrows JasperException {
            visitBody(n);
        }
        public void visit(Node.JspBody nthrows JasperException {
            doSmap(n);
            visitBody(n);
        }
        public void visit(Node.InvokeAction nthrows JasperException {
            doSmap(n);
            visitBody(n);
        }
        public void visit(Node.DoBodyAction nthrows JasperException {
            doSmap(n);
            visitBody(n);
        }
        public void visit(Node.ELExpression nthrows JasperException {
            doSmap(n);
        }
        public void visit(Node.TemplateText nthrows JasperException {
            Mark mark = n.getStart();
            if (mark == null) {
                return;
            }
            //Add the file information
            String fileName = mark.getFile();
            .addFile(unqualify(fileName), fileName);
            //Add a LineInfo that corresponds to the beginning of this node
            int iInputStartLine = mark.getLineNumber();
            int iOutputStartLine = n.getBeginJavaLine();
            int iOutputLineIncrement = ? 1: 0;
            .addLineData(iInputStartLinefileName, 1, iOutputStartLine
                             iOutputLineIncrement);
            // Output additional mappings in the text
            java.util.ArrayList extraSmap = n.getExtraSmap();
            if (extraSmap != null) {
                for (int i = 0; i < extraSmap.size(); i++) {
                    iOutputStartLine += iOutputLineIncrement;
                    .addLineData(
                        iInputStartLine+((Integer)extraSmap.get(i)).intValue(),
                        fileName,
                        1,
                        iOutputStartLine,
                        iOutputLineIncrement);
                }
            }
        }
        private void doSmap(
            Node n,
            int inLineCount,
            int outIncrement,
            int skippedLines) {
            Mark mark = n.getStart();
            if (mark == null) {
                return;
            }
            String unqualifiedName = unqualify(mark.getFile());
            .addFile(unqualifiedNamemark.getFile());
            .addLineData(
                mark.getLineNumber() + skippedLines,
                mark.getFile(),
                inLineCount - skippedLines,
                n.getBeginJavaLine() + skippedLines,
                outIncrement);
        }
        private void doSmap(Node n) {
            doSmap(n, 1, n.getEndJavaLine() - n.getBeginJavaLine(), 0);
        }
        private void doSmapText(Node n) {
            String text = n.getText();
            int index = 0;
            int next = 0;
            int lineCount = 1;
            int skippedLines = 0;
            boolean slashStarSeen = false;
            boolean beginning = true;
            // Count lines inside text, but skipping comment lines at the
            // beginning of the text.
            while ((next = text.indexOf('\n'index)) > -1) {
                if (beginning) {
                    String line = text.substring(indexnext).trim();
                    if (!slashStarSeen && line.startsWith("/*")) {
                        slashStarSeen = true;
                    }
                    if (slashStarSeen) {
                        skippedLines++;
                        int endIndex = line.indexOf("*/");
                        if (endIndex >= 0) {
                            // End of /* */ comment
                            slashStarSeen = false;
                            if (endIndex < line.length() - 2) {
                                // Some executable code after comment
                                skippedLines--;
                                beginning = false;
                            }
                        }
                    } else if (line.length() == 0 || line.startsWith("//")) {
                        skippedLines++;
                    } else {
                        beginning = false;
                    }
                }
                lineCount++;
                index = next + 1;
            }
            doSmap(nlineCount, 1, skippedLines);
        }
    }
    private static class PreScanVisitor extends Node.Visitor {
        HashMap map = new HashMap();
        public void doVisit(Node n) {
            String inner = n.getInnerClassName();
            if (inner != null && !.containsKey(inner)) {
                .put(innernew SmapStratum("JSP"));
            }
        }
        HashMap getMap() {
            return ;
        }
    }
    
New to GrepCode? Check out our FAQ X