View | Details | Raw Unified | Return to bug 159888 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelper.java (-211 / +15 lines)
Lines 11-26 Link Here
11
package org.eclipse.jst.jsp.core.internal.taglib;
11
package org.eclipse.jst.jsp.core.internal.taglib;
12
12
13
13
14
import java.io.File;
15
import java.util.ArrayList;
14
import java.util.ArrayList;
16
import java.util.Collection;
15
import java.util.Collection;
17
import java.util.HashMap;
16
import java.util.HashMap;
18
import java.util.HashSet;
19
import java.util.Hashtable;
17
import java.util.Hashtable;
20
import java.util.Iterator;
18
import java.util.Iterator;
21
import java.util.List;
19
import java.util.List;
22
import java.util.Map;
20
import java.util.Map;
23
import java.util.Set;
24
21
25
import javax.servlet.jsp.tagext.TagAttributeInfo;
22
import javax.servlet.jsp.tagext.TagAttributeInfo;
26
import javax.servlet.jsp.tagext.TagData;
23
import javax.servlet.jsp.tagext.TagData;
Lines 30-45 Link Here
30
import javax.servlet.jsp.tagext.ValidationMessage;
27
import javax.servlet.jsp.tagext.ValidationMessage;
31
import javax.servlet.jsp.tagext.VariableInfo;
28
import javax.servlet.jsp.tagext.VariableInfo;
32
29
33
import org.eclipse.core.resources.IFile;
34
import org.eclipse.core.resources.IFolder;
35
import org.eclipse.core.resources.IProject;
30
import org.eclipse.core.resources.IProject;
36
import org.eclipse.core.resources.ResourcesPlugin;
37
import org.eclipse.core.runtime.CoreException;
38
import org.eclipse.core.runtime.IPath;
31
import org.eclipse.core.runtime.IPath;
39
import org.eclipse.core.runtime.NullProgressMonitor;
32
import org.eclipse.core.runtime.NullProgressMonitor;
40
import org.eclipse.core.runtime.Platform;
33
import org.eclipse.core.runtime.Platform;
41
import org.eclipse.jdt.core.IClasspathContainer;
42
import org.eclipse.jdt.core.IClasspathEntry;
43
import org.eclipse.jdt.core.IJavaProject;
34
import org.eclipse.jdt.core.IJavaProject;
44
import org.eclipse.jdt.core.JavaCore;
35
import org.eclipse.jdt.core.JavaCore;
45
import org.eclipse.jdt.core.JavaModelException;
36
import org.eclipse.jdt.core.JavaModelException;
Lines 83-99 Link Here
83
	}
74
	}
84
75
85
	private IProject fProject = null;
76
	private IProject fProject = null;
86
	private TaglibClassLoader fLoader = null;
77
	private ClassLoader fLoader = null;
87
78
88
	private Set fProjectEntries = null;
89
	private Map fTranslationProblems = null;
79
	private Map fTranslationProblems = null;
90
	private Set fContainerEntries = null;
91
	private IJavaProject fJavaProject;
80
	private IJavaProject fJavaProject;
92
81
93
	public TaglibHelper(IProject project) {
82
	public TaglibHelper(IProject project) {
83
		super();
94
		setProject(project);
84
		setProject(project);
95
		fProjectEntries = new HashSet();
96
		fContainerEntries = new HashSet();
97
		fTranslationProblems = new HashMap();
85
		fTranslationProblems = new HashMap();
98
	}
86
	}
99
87
Lines 178-184 Link Here
178
	 * @param node
166
	 * @param node
179
	 */
167
	 */
180
	private void addVariables(List results, CMNode node, ITextRegionCollection customTag) {
168
	private void addVariables(List results, CMNode node, ITextRegionCollection customTag) {
181
182
		List list = ((TLDElementDeclaration) node).getVariables();
169
		List list = ((TLDElementDeclaration) node).getVariables();
183
		Iterator it = list.iterator();
170
		Iterator it = list.iterator();
184
		while (it.hasNext()) {
171
		while (it.hasNext()) {
Lines 240-246 Link Here
240
		if (teiClassname == null || teiClassname.length() == 0 || fJavaProject == null)
227
		if (teiClassname == null || teiClassname.length() == 0 || fJavaProject == null)
241
			return;
228
			return;
242
229
243
		TaglibClassLoader loader = getClassloader();
230
		ClassLoader loader = getClassloader();
244
231
245
		Class teiClass = null;
232
		Class teiClass = null;
246
		try {
233
		try {
Lines 611-817 Link Here
611
		return tagDataTable;
598
		return tagDataTable;
612
	}
599
	}
613
600
614
	private TaglibClassLoader getClassloader() {
601
	private ClassLoader getClassloader() {
615
		if (fLoader == null) {
602
		if (fLoader == null) {
616
			fLoader = new TaglibClassLoader(this.getClass().getClassLoader());
603
			fLoader = new BuildPathClassLoader(fJavaProject);
617
			fProjectEntries.clear();
618
			fContainerEntries.clear();
619
			addClasspathEntriesForProject(getProject(), fLoader);
620
		}
604
		}
621
		return fLoader;
605
		return fLoader;
622
	}
606
	}
623
607
624
	/**
608
	/**
625
	 * @param loader
626
	 */
627
	private void addClasspathEntriesForProject(IProject p, TaglibClassLoader loader) {
628
629
		// avoid infinite recursion and closed project
630
		if (!p.isAccessible() || fProjectEntries.contains(p.getFullPath().toString()))
631
			return;
632
		fProjectEntries.add(p.getFullPath().toString());
633
634
		// add things on classpath that we are interested in
635
		try {
636
			if (p.hasNature(JavaCore.NATURE_ID)) {
637
638
				IJavaProject project = JavaCore.create(p);
639
640
				try {
641
					IClasspathEntry[] entries = project.getResolvedClasspath(true);
642
					addDefaultDirEntry(loader, project);
643
					addClasspathEntries(loader, project, entries);
644
				}
645
				catch (JavaModelException e) {
646
					Logger.logException(e);
647
				}
648
			}
649
		}
650
		catch (CoreException e) {
651
			Logger.logException(e);
652
		}
653
	}
654
655
	private void addClasspathEntries(TaglibClassLoader loader, IJavaProject project, IClasspathEntry[] entries) throws JavaModelException {
656
		IClasspathEntry entry;
657
		for (int i = 0; i < entries.length; i++) {
658
659
			entry = entries[i];
660
			if (DEBUG)
661
				System.out.println("current entry is: " + entry); //$NON-NLS-1$
662
663
			switch (entry.getEntryKind()) {
664
				case IClasspathEntry.CPE_SOURCE :
665
					addSourceEntry(loader, entry);
666
					break;
667
				case IClasspathEntry.CPE_LIBRARY :
668
					addLibraryEntry(loader, entry.getPath());
669
					break;
670
				case IClasspathEntry.CPE_PROJECT :
671
					addProjectEntry(loader, entry);
672
					break;
673
				case IClasspathEntry.CPE_VARIABLE :
674
					addVariableEntry(loader, entry);
675
					break;
676
				case IClasspathEntry.CPE_CONTAINER :
677
					addContainerEntry(loader, project, entry);
678
					break;
679
			}
680
		}
681
	}
682
683
	/**
684
	 * @param loader
685
	 * @param entry
686
	 */
687
	private void addVariableEntry(TaglibClassLoader loader, IClasspathEntry entry) {
688
		if (DEBUG)
689
			System.out.println(" -> adding variable entry: [" + entry + "]"); //$NON-NLS-1$ //$NON-NLS-2$
690
691
		// variable should either be a project or a library entry
692
693
		// BUG 169431
694
		String variableName = entry.getPath().toString();
695
		IPath variablePath = JavaCore.getResolvedVariablePath(entry.getPath());
696
		variablePath = JavaCore.getClasspathVariable(variableName);
697
698
		// RATLC01076854
699
		// variable paths may not exist
700
		// in that case null will be returned
701
		if (variablePath != null) {
702
			if (variablePath.segments().length == 1) {
703
				IProject varProj = ResourcesPlugin.getWorkspace().getRoot().getProject(variablePath.toString());
704
				if (varProj != null && varProj.exists()) {
705
					addClasspathEntriesForProject(varProj, loader);
706
					return;
707
				}
708
			}
709
			addLibraryEntry(loader, variablePath);
710
		}
711
	}
712
713
	/**
714
	 * @param loader
715
	 * @param project
716
	 * @param entry
717
	 * @throws JavaModelException
718
	 */
719
	private void addContainerEntry(TaglibClassLoader loader, IJavaProject project, IClasspathEntry entry) throws JavaModelException {
720
721
		IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), project);
722
		if (container != null) {
723
			String uniqueProjectAndContainerPath = project.getProject().getFullPath().append(container.getPath()).toString();
724
			/*
725
			 * Avoid infinite recursion, but track containers for each project
726
			 * separately as they may return different values. This may mean
727
			 * indexing JREs multiple times, however.
728
			 */
729
			if (!fContainerEntries.contains(uniqueProjectAndContainerPath)) {
730
				fContainerEntries.add(uniqueProjectAndContainerPath);
731
732
				IClasspathEntry[] cpes = container.getClasspathEntries();
733
				// recursive call here
734
				addClasspathEntries(loader, project, cpes);
735
			}
736
		}
737
	}
738
739
	/**
740
	 * @param loader
741
	 * @param entry
742
	 */
743
	private void addProjectEntry(TaglibClassLoader loader, IClasspathEntry entry) {
744
		if (DEBUG)
745
			System.out.println(" -> project entry: [" + entry + "]"); //$NON-NLS-1$ //$NON-NLS-2$
746
747
		IPath path = entry.getPath();
748
		IProject referenceProject = ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0));
749
		if (referenceProject != null && referenceProject.isAccessible()) {
750
			addClasspathEntriesForProject(referenceProject, loader);
751
		}
752
	}
753
754
	/**
755
	 * @param loader
756
	 * @param project
757
	 * @param projectLocation
758
	 * @throws JavaModelException
759
	 */
760
	private void addDefaultDirEntry(TaglibClassLoader loader, IJavaProject project) throws JavaModelException {
761
		// add default bin directory for the project
762
		IPath outputPath = project.getOutputLocation();
763
		loader.addFolder(outputPath);
764
	}
765
766
	/**
767
	 * @param loader
768
	 * @param entry
769
	 */
770
	private void addLibraryEntry(TaglibClassLoader loader, IPath libPath) {
771
		String libPathString = libPath.toString();
772
		File file = new File(libPathString);
773
774
		if (file.exists()) {
775
			if (file.isDirectory()) {
776
				loader.addDirectory(libPathString);
777
			}
778
			else {
779
				loader.addJar(libPathString);
780
			}
781
		}
782
		else {
783
			if (libPath.segmentCount() > 1) {
784
				IFile ifile = ResourcesPlugin.getWorkspace().getRoot().getFile(libPath);
785
				if (ifile != null && ifile.isAccessible()) {
786
					loader.addFile(libPath);
787
				}
788
				else {
789
					IFolder ifolder = ResourcesPlugin.getWorkspace().getRoot().getFolder(libPath);
790
					if (ifolder != null && ifolder.isAccessible()) {
791
						loader.addFolder(libPath);
792
					}
793
				}
794
			}
795
			else {
796
				loader.addFolder(libPath);
797
			}
798
		}
799
	}
800
801
	/**
802
	 * @param loader
803
	 * @param entry
804
	 */
805
	private void addSourceEntry(TaglibClassLoader loader, IClasspathEntry entry) {
806
		// add bin directory for specific entry if it has
807
		// one
808
		IPath outputLocation = entry.getOutputLocation();
809
		if (outputLocation != null) {
810
			loader.addFolder(outputLocation);
811
		}
812
	}
813
814
	/**
815
	 * @return Returns the fModelQuery.
609
	 * @return Returns the fModelQuery.
816
	 */
610
	 */
817
	public ModelQuery getModelQuery(IDocument doc) {
611
	public ModelQuery getModelQuery(IDocument doc) {
Lines 880-883 Link Here
880
			}
674
			}
881
		}
675
		}
882
	}
676
	}
677
678
	/**
679
	 * 
680
	 */
681
	public void dispose() {
682
		fLoader = null;
683
		fJavaProject = null;
684
		fProject = null;
685
		fTranslationProblems = null;
686
	}
883
}
687
}
(-)src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelperCache.java (-2 / +4 lines)
Lines 129-137 Link Here
129
        }
129
        }
130
        if(fHelpers.size() > MAX_SIZE) {
130
        if(fHelpers.size() > MAX_SIZE) {
131
            // one too many, remove last
131
            // one too many, remove last
132
            Object removed = fHelpers.remove(fHelpers.size()-1);
132
        	Entry removed = (Entry) fHelpers.remove(fHelpers.size()-1);
133
        	removed.getHelper().dispose();
133
            if(DEBUG) {
134
            if(DEBUG) {
134
            	Logger.log(Logger.INFO, "(-) TaglibHelperCache removed: " + removed); //$NON-NLS-1$
135
            	Logger.log(Logger.INFO, "(-) TaglibHelperCache removed: " + removed.getProjectName()); //$NON-NLS-1$
135
                printCacheContents();
136
                printCacheContents();
136
            }
137
            }
137
        }
138
        }
Lines 144-149 Link Here
144
        while(it.hasNext()) {
145
        while(it.hasNext()) {
145
            entry = (Entry)it.next();
146
            entry = (Entry)it.next();
146
            if(entry.getProjectName().equals(projectName)) {
147
            if(entry.getProjectName().equals(projectName)) {
148
            	entry.getHelper().dispose();
147
                fHelpers.remove(entry);
149
                fHelpers.remove(entry);
148
                if(DEBUG) { 
150
                if(DEBUG) { 
149
                    Logger.log(Logger.INFO, "(-) TaglibHelperCache removed: " + entry); //$NON-NLS-1$
151
                    Logger.log(Logger.INFO, "(-) TaglibHelperCache removed: " + entry); //$NON-NLS-1$
(-)src/org/eclipse/jst/jsp/core/internal/taglib/BuildPathClassLoader.java (+189 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jst.jsp.core.internal.taglib;
12
13
import java.io.ByteArrayOutputStream;
14
import java.io.File;
15
import java.io.IOException;
16
import java.io.InputStream;
17
import java.util.zip.ZipEntry;
18
import java.util.zip.ZipFile;
19
20
import org.eclipse.core.resources.IFile;
21
import org.eclipse.core.resources.ResourcesPlugin;
22
import org.eclipse.core.runtime.CoreException;
23
import org.eclipse.core.runtime.IPath;
24
import org.eclipse.core.runtime.Platform;
25
import org.eclipse.jdt.core.IJavaProject;
26
import org.eclipse.jdt.core.IType;
27
import org.eclipse.jdt.core.JavaModelException;
28
import org.eclipse.jst.jsp.core.internal.Logger;
29
import org.eclipse.wst.sse.core.utils.StringUtils;
30
31
/**
32
 * Custom ClassLoader backed by a Java Project.
33
 */
34
public class BuildPathClassLoader extends ClassLoader {
35
	private static final boolean DEBUG = Boolean.valueOf(Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/taglibclassloader")).booleanValue(); //$NON-NLS-1$
36
	private IJavaProject fProject;
37
38
	public BuildPathClassLoader(IJavaProject project) {
39
		super();
40
		fProject = project;
41
	}
42
43
	/**
44
	 * Closes the given file with "extreme prejudice".
45
	 * 
46
	 * @param file
47
	 */
48
	public void closeJarFile(ZipFile file) {
49
		if (file == null)
50
			return;
51
		try {
52
			file.close();
53
		}
54
		catch (IOException ioe) {
55
			// no cleanup can be done
56
			Logger.logException("JarUtilities: Could not close file " + file.getName(), ioe); //$NON-NLS-1$
57
		}
58
	}
59
60
	/*
61
	 * This may pose a runtime performance problem as it opens the containing
62
	 * .jar file for each class, but this is countered by no longer leaving
63
	 * file handles open nor having to directly interact the build path at
64
	 * all. If it is a problem, the TaglibHelper should control some
65
	 * "batching" whereby we leave the JarFiles open until directed to close
66
	 * them at the end of TaglibHelper.addTEIVariables(...).
67
	 * 
68
	 * @see java.lang.ClassLoader#findClass(java.lang.String)
69
	 */
70
	protected Class findClass(String className) throws ClassNotFoundException {
71
		if (DEBUG)
72
			System.out.println("finding: [" + className + "]"); //$NON-NLS-1$ //$NON-NLS-2$
73
		try {
74
			IType type = fProject.findType(className);
75
			if (type != null) {
76
				IPath path = type.getPath();
77
				// needs to be compiled before we can load it
78
				if ("class".equalsIgnoreCase(path.getFileExtension())) {
79
					IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
80
					if (file.isAccessible()) {
81
						byte[] bytes = loadBytes(file);
82
						return defineClass(className, bytes, 0, bytes.length);
83
					}
84
				}
85
				else if ("jar".equalsIgnoreCase(path.getFileExtension())) {
86
					String expectedFileName = StringUtils.replace(className, ".", "/").concat(".class");
87
					byte[] bytes = getCachedInputStream(path.toOSString(), expectedFileName);
88
					return defineClass(className, bytes, 0, bytes.length);
89
				}
90
			}
91
		}
92
		catch (JavaModelException e) {
93
			Logger.logException(e);
94
		}
95
		return super.findClass(className);
96
	}
97
98
	private byte[] getCachedInputStream(String jarFilename, String entryName) {
99
		ByteArrayOutputStream buffer = null;
100
101
		File testFile = new File(jarFilename);
102
		if (!testFile.exists())
103
			return null;
104
105
		ZipFile jarfile = null;
106
		try {
107
			jarfile = new ZipFile(jarFilename);
108
		}
109
		catch (IOException ioExc) {
110
			Logger.logException("JarUtilities: " + jarFilename, ioExc); //$NON-NLS-1$
111
			closeJarFile(jarfile);
112
		}
113
114
		if (jarfile != null) {
115
			try {
116
				ZipEntry zentry = jarfile.getEntry(entryName);
117
				if (zentry != null) {
118
					InputStream entryInputStream = null;
119
					try {
120
						entryInputStream = jarfile.getInputStream(zentry);
121
					}
122
					catch (IOException ioExc) {
123
						Logger.logException("JarUtilities: " + jarFilename, ioExc); //$NON-NLS-1$
124
					}
125
126
					if (entryInputStream != null) {
127
						int c;
128
						if (zentry.getSize() > 0) {
129
							buffer = new ByteArrayOutputStream((int) zentry.getSize());
130
						}
131
						else {
132
							buffer = new ByteArrayOutputStream();
133
						}
134
						// array dim restriction?
135
						byte bytes[] = new byte[2048];
136
						try {
137
							while ((c = entryInputStream.read(bytes)) >= 0) {
138
								buffer.write(bytes, 0, c);
139
							}
140
							closeJarFile(jarfile);
141
						}
142
						catch (IOException ioe) {
143
							// no cleanup can be done
144
						}
145
						finally {
146
							try {
147
								entryInputStream.close();
148
							}
149
							catch (IOException e) {
150
							}
151
						}
152
					}
153
				}
154
			}
155
			finally {
156
				closeJarFile(jarfile);
157
			}
158
		}
159
160
		if (buffer != null) {
161
			return buffer.toByteArray();
162
		}
163
		return new byte[0];
164
	}
165
166
	/**
167
	 * @param file
168
	 * @return
169
	 */
170
	private byte[] loadBytes(IFile file) {
171
		ByteArrayOutputStream out = new ByteArrayOutputStream();
172
		try {
173
			InputStream in = file.getContents();
174
			byte[] buffer = new byte[4096];
175
			int read = in.read(buffer);
176
			while (read != -1) {
177
				out.write(buffer, 0, read);
178
			}
179
		}
180
		catch (CoreException e) {
181
			Logger.logException(e);
182
		}
183
		catch (IOException e) {
184
			Logger.logException(e);
185
		}
186
		return out.toByteArray();
187
	}
188
189
}

Return to bug 159888