1 19 20 package org.netbeans.modules.web.core.syntax; 21 import java.io.IOException ; 22 import java.io.PrintWriter ; 23 import java.lang.ref.WeakReference ; 24 import java.util.ArrayList ; 25 import java.util.List ; 26 import java.util.logging.Level ; 27 import java.util.logging.Logger ; 28 import javax.swing.text.BadLocationException ; 29 import javax.swing.text.Document ; 30 import org.netbeans.api.java.source.ClasspathInfo; 31 import org.netbeans.api.java.source.JavaSource; 32 import org.netbeans.api.jsp.lexer.JspTokenId; 33 import org.netbeans.api.lexer.Token; 34 import org.netbeans.api.lexer.TokenHierarchy; 35 import org.netbeans.api.lexer.TokenSequence; 36 import org.netbeans.editor.BaseDocument; 37 import org.netbeans.modules.editor.NbEditorUtilities; 38 import org.netbeans.modules.web.core.syntax.JspSyntaxSupport; 39 import org.netbeans.modules.web.jsps.parserapi.PageInfo; 40 import org.netbeans.spi.editor.completion.CompletionItem; 41 import org.openide.filesystems.FileObject; 42 import org.openide.filesystems.FileSystem; 43 import org.openide.filesystems.FileUtil; 44 45 import static org.netbeans.api.jsp.lexer.JspTokenId.JavaCodeType; 46 47 58 public class SimplifiedJSPServlet { 59 private static final String CLASS_HEADER = "\nclass SimplifiedJSPServlet extends HttpServlet {\n" + "\tHttpServletRequest request;\n" + "\tHttpServletResponse response;\n" + "\tHttpSession session;\n" + "\tServletContext application;\n" + "\tJspWriter out;\n" + "\tServletConfig config;\n" + "\tJspContext jspContext;\n" + "\tObject page;\n" + "\tPageContext pageContext;\n"; 70 private static final String METHOD_HEADER = "\n\tvoid mergedScriptlets(){\n\n"; private static final String CLASS_FOOTER = "\n\t}\n}"; 73 @Deprecated 74 private final JspSyntaxSupport sup; 75 76 private final Document doc; 77 private final ArrayList <CodeBlockData> codeBlocks = new ArrayList <CodeBlockData>(); 78 79 private String mergedScriptlets = null; 80 private String mergedDeclarations = null; 81 private boolean processCalled = false; 82 private String importStatements = null; 83 private int expressionIndex = 1; 84 private static final Logger logger = Logger.getLogger(SimplifiedJSPServlet.class.getName()); 85 86 87 public SimplifiedJSPServlet(Document doc) { 88 this.doc = doc; 89 90 sup = (JspSyntaxSupport)((BaseDocument)doc).getSyntaxSupport(); 91 } 92 93 public void process() throws BadLocationException { 94 processCalled = true; 95 StringBuilder buffScriplets = new StringBuilder (); 96 StringBuilder buffDeclarations = new StringBuilder (); 97 98 TokenHierarchy tokenHierarchy = TokenHierarchy.get(doc); 99 TokenSequence tokenSequence = tokenHierarchy.tokenSequence(); 101 if(!tokenSequence.moveNext()) { 102 return ; } 104 105 109 do{ 110 Token token = tokenSequence.token(); 111 112 if (token.id() == JspTokenId.SCRIPTLET){ 113 int blockStart = token.offset(tokenHierarchy); 114 int blockEnd = blockStart + token.length(); 115 116 JavaCodeType blockType = (JavaCodeType)token.getProperty(JspTokenId.SCRIPTLET_TOKEN_TYPE_PROPERTY);; 117 118 String blockBody = doc.getText(blockStart, blockEnd - blockStart); 119 StringBuilder buff = blockType == JavaCodeType.DECLARATION ? buffDeclarations : buffScriplets; 120 int newBlockStart = buff.length(); 121 122 if (blockType == JavaCodeType.EXPRESSION){ 123 String exprPrefix = String.format("\t\tObject expr%1$d = ", expressionIndex ++); newBlockStart += exprPrefix.length(); 125 buff.append(exprPrefix + blockBody + ";\n"); 126 } else{ 127 buff.append(blockBody + "\n"); 128 } 129 130 CodeBlockData blockData = new CodeBlockData(blockStart, newBlockStart, blockEnd, blockType); 131 codeBlocks.add(blockData); 132 } 133 } while (tokenSequence.moveNext()); 134 135 importStatements = createImportStatements(); 136 mergedDeclarations = buffDeclarations + "\n" + createBeanVarDeclarations(); 137 mergedScriptlets = buffScriplets.toString(); 138 } 139 140 private String createBeanVarDeclarations(){ 141 StringBuilder beanDeclarationsBuff = new StringBuilder (); 142 143 PageInfo.BeanData[] beanData = sup.getBeanData(); 144 145 for (PageInfo.BeanData bean: beanData){ 146 beanDeclarationsBuff.append(bean.getClassName() + " " + bean.getId() + ";\n"); } 148 149 return beanDeclarationsBuff.toString(); 150 } 151 152 private String createImportStatements(){ 153 StringBuilder importsBuff = new StringBuilder (); 154 String imports[] = sup.getImports(); 155 156 for (String pckg : sup.getImports()){ 157 importsBuff.append("import " + pckg + ";\n"); } 159 160 return importsBuff.toString(); 161 } 162 163 private void assureProcessCalled(){ 164 if (!processCalled){ 165 throw new IllegalStateException ("process() method must be called first!"); } 167 } 168 169 public int getShiftedOffset(int originalOffset){ 170 assureProcessCalled(); 171 172 CodeBlockData codeBlock = getCodeBlockAtOffset(originalOffset); 173 174 if (codeBlock == null){ 175 return -1; } 177 178 int offsetWithinBlock = originalOffset - codeBlock.getStartOffset(); 179 int shiftedOffset = codeBlock.getNewBlockStart() + offsetWithinBlock; 180 181 return shiftedOffset; 182 } 183 184 public String getVirtualClassBody(){ 185 assureProcessCalled(); 186 return importStatements + CLASS_HEADER + mergedDeclarations + METHOD_HEADER 187 + mergedScriptlets + CLASS_FOOTER; 188 } 189 190 private CodeBlockData getCodeBlockAtOffset(int offset){ 191 192 for (CodeBlockData codeBlock : codeBlocks){ 193 if (codeBlock.getStartOffset() <= offset && codeBlock.getEndOffset() >= offset){ 194 return codeBlock; 195 } 196 } 197 198 return null; 199 } 200 201 public abstract static class VirtualJavaClass{ 202 203 public final void create(Document doc, String virtualClassBody){ 204 FileObject fileDummyJava = null; 205 List <? extends CompletionItem> javaCompletionItems = null; 206 207 try { 208 FileSystem memFS = FileUtil.createMemoryFileSystem(); 209 fileDummyJava = memFS.getRoot().createData("SimplifiedJSPServlet", "java"); PrintWriter writer = new PrintWriter (fileDummyJava.getOutputStream()); 211 writer.print(virtualClassBody); 212 writer.close(); 213 214 FileObject jspFile = NbEditorUtilities.getFileObject(doc); 215 ClasspathInfo cpInfo = ClasspathInfo.create(jspFile); 216 217 final JavaSource source = JavaSource.create(cpInfo, fileDummyJava); 218 219 doc.putProperty(JavaSource.class, new WeakReference <JavaSource>(null) { 220 public JavaSource get() { 221 return source; 222 } 223 }); 224 225 process(fileDummyJava, source); 226 227 } catch (IOException ex) { 228 logger.log(Level.SEVERE, ex.getMessage(), ex); 229 } 239 } 240 241 protected abstract void process(FileObject fileObject, JavaSource javaSource); 242 } 243 244 private class CodeBlockData { 245 private int startOffset; 246 private int endOffset; 247 private int newRelativeBlockStart; private JavaCodeType type; 249 250 public CodeBlockData(int startOffset, int newRelativeBlockStart, int endOffset, JavaCodeType type){ 251 this.startOffset = startOffset; 252 this.newRelativeBlockStart = newRelativeBlockStart; 253 this.endOffset = endOffset; 254 this.type = type; 255 } 256 257 public int getStartOffset(){ 258 return startOffset; 259 } 260 261 public int getEndOffset(){ 262 return endOffset; 263 } 264 265 public JavaCodeType getType(){ 266 return type; 267 } 268 269 public int getNewBlockStart(){ 270 int newBlockStart = newRelativeBlockStart + CLASS_HEADER.length() + importStatements.length(); 271 272 if (getType() != JavaCodeType.DECLARATION){ 273 newBlockStart += mergedDeclarations.length() + METHOD_HEADER.length(); 274 } 275 276 return newBlockStart; 277 } 278 } 279 } 280 | Popular Tags |