KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > web > core > syntax > SimplifiedJSPServlet


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.web.core.syntax;
21 import java.io.IOException JavaDoc;
22 import java.io.PrintWriter JavaDoc;
23 import java.lang.ref.WeakReference JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.logging.Level JavaDoc;
27 import java.util.logging.Logger JavaDoc;
28 import javax.swing.text.BadLocationException JavaDoc;
29 import javax.swing.text.Document JavaDoc;
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 /**
48  * Utility class for generating a simplified <em>JSP servlet</em> class from a JSP file.
49  * Using a full featured JSP parser would be too resource demanding,
50  * we need a lightweight solution to be used with code completion.
51  *
52  * Inputs: original JSP document, caret offset within the original document
53  * Outputs: a body of a simplified JSP servlet class, offset of the corresponding
54  * position in the servlet class
55  *
56  * @author Tomasz.Slota@Sun.COM
57  */

58 public class SimplifiedJSPServlet {
59     private static final String JavaDoc CLASS_HEADER = "\nclass SimplifiedJSPServlet extends HttpServlet {\n" + //NOI18N
60
"\tHttpServletRequest request;\n" + //NOI18N
61
"\tHttpServletResponse response;\n" + //NOI18N
62
"\tHttpSession session;\n" + //NOI18N
63
"\tServletContext application;\n" + //NOI18N
64
"\tJspWriter out;\n" + //NOI18N
65
"\tServletConfig config;\n" + //NOI18N
66
"\tJspContext jspContext;\n" + //NOI18N
67
"\tObject page;\n" + //NOI18N
68
"\tPageContext pageContext;\n"; //NOI18N
69

70     private static final String JavaDoc METHOD_HEADER = "\n\tvoid mergedScriptlets(){\n\n"; //NOI18N
71
private static final String JavaDoc CLASS_FOOTER = "\n\t}\n}"; //NOI18N
72

73     @Deprecated JavaDoc
74     private final JspSyntaxSupport sup;
75     
76     private final Document JavaDoc doc;
77     private final ArrayList JavaDoc<CodeBlockData> codeBlocks = new ArrayList JavaDoc<CodeBlockData>();
78     
79     private String JavaDoc mergedScriptlets = null;
80     private String JavaDoc mergedDeclarations = null;
81     private boolean processCalled = false;
82     private String JavaDoc importStatements = null;
83     private int expressionIndex = 1;
84     private static final Logger JavaDoc logger = Logger.getLogger(SimplifiedJSPServlet.class.getName());
85     
86     /** Creates a new instance of ScripletsBodyExtractor */
87     public SimplifiedJSPServlet(Document JavaDoc doc) {
88         this.doc = doc;
89         
90         sup = (JspSyntaxSupport)((BaseDocument)doc).getSyntaxSupport();
91     }
92     
93     public void process() throws BadLocationException JavaDoc{
94         processCalled = true;
95         StringBuilder JavaDoc buffScriplets = new StringBuilder JavaDoc();
96         StringBuilder JavaDoc buffDeclarations = new StringBuilder JavaDoc();
97         
98         TokenHierarchy tokenHierarchy = TokenHierarchy.get(doc);
99         TokenSequence tokenSequence = tokenHierarchy.tokenSequence(); //get top level token sequence
100

101         if(!tokenSequence.moveNext()) {
102             return ; //no tokens in token sequence
103
}
104         
105         /**
106          * process java code blocks one by one
107          * note: We count on the fact the scripting language in JSP is Java
108          */

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 JavaDoc blockBody = doc.getText(blockStart, blockEnd - blockStart);
119                 StringBuilder JavaDoc buff = blockType == JavaCodeType.DECLARATION ? buffDeclarations : buffScriplets;
120                 int newBlockStart = buff.length();
121                 
122                 if (blockType == JavaCodeType.EXPRESSION){
123                     String JavaDoc exprPrefix = String.format("\t\tObject expr%1$d = ", expressionIndex ++); //NOI18N
124
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 JavaDoc createBeanVarDeclarations(){
141         StringBuilder JavaDoc beanDeclarationsBuff = new StringBuilder JavaDoc();
142         
143         PageInfo.BeanData[] beanData = sup.getBeanData();
144         
145         for (PageInfo.BeanData bean: beanData){
146             beanDeclarationsBuff.append(bean.getClassName() + " " + bean.getId() + ";\n"); //NOI18N
147
}
148         
149         return beanDeclarationsBuff.toString();
150     }
151     
152     private String JavaDoc createImportStatements(){
153         StringBuilder JavaDoc importsBuff = new StringBuilder JavaDoc();
154         String JavaDoc imports[] = sup.getImports();
155         
156         for (String JavaDoc pckg : sup.getImports()){
157             importsBuff.append("import " + pckg + ";\n"); //NOI18N
158
}
159         
160         return importsBuff.toString();
161     }
162     
163     private void assureProcessCalled(){
164         if (!processCalled){
165             throw new IllegalStateException JavaDoc("process() method must be called first!");//NOI18N
166
}
167     }
168     
169     public int getShiftedOffset(int originalOffset){
170         assureProcessCalled();
171         
172         CodeBlockData codeBlock = getCodeBlockAtOffset(originalOffset);
173         
174         if (codeBlock == null){
175             return -1; // no embedded java code at the offset
176
}
177         
178         int offsetWithinBlock = originalOffset - codeBlock.getStartOffset();
179         int shiftedOffset = codeBlock.getNewBlockStart() + offsetWithinBlock;
180         
181         return shiftedOffset;
182     }
183     
184     public String JavaDoc 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 JavaDoc doc, String JavaDoc virtualClassBody){
204             FileObject fileDummyJava = null;
205             List JavaDoc<? extends CompletionItem> javaCompletionItems = null;
206             
207             try {
208                 FileSystem memFS = FileUtil.createMemoryFileSystem();
209                 fileDummyJava = memFS.getRoot().createData("SimplifiedJSPServlet", "java"); //NOI18N
210
PrintWriter JavaDoc writer = new PrintWriter JavaDoc(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 JavaDoc<JavaSource>(null) {
220                     public JavaSource get() {
221                         return source;
222                     }
223                 });
224                 
225                 process(fileDummyJava, source);
226                 
227             } catch (IOException JavaDoc ex) {
228                 logger.log(Level.SEVERE, ex.getMessage(), ex);
229             }/* finally{
230             if (fileDummyJava != null){
231                 try{
232                     fileDummyJava.delete();
233               
234                 } catch (IOException e){
235                     logger.log(Level.SEVERE, e.getMessage(), e);
236                 }
237             }
238         }*/

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; // offset in created java class
248
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