| /******************************************************************************* |
| * Copyright (c) 2008 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * bug:244839 - eugene@genuitec.com |
| * |
| * Provisional API: This class/interface is part of an interim API that is still under development and expected to |
| * change significantly before reaching stability. It is being made available at this early stage to solicit feedback |
| * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken |
| * (repeatedly) as the API evolves. |
| * |
| * |
| *******************************************************************************/ |
| |
| |
| package org.eclipse.wst.jsdt.web.core.javascript; |
| |
| import java.io.IOException; |
| import java.io.UnsupportedEncodingException; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Vector; |
| |
| import org.eclipse.core.filebuffers.FileBuffers; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.Position; |
| import org.eclipse.wst.jsdt.core.IBuffer; |
| import org.eclipse.wst.jsdt.core.IJavaScriptElement; |
| import org.eclipse.wst.jsdt.core.IJavaScriptProject; |
| import org.eclipse.wst.jsdt.core.IJavaScriptUnit; |
| import org.eclipse.wst.jsdt.core.IPackageFragmentRoot; |
| import org.eclipse.wst.jsdt.core.ISourceRange; |
| import org.eclipse.wst.jsdt.core.JavaScriptModelException; |
| import org.eclipse.wst.jsdt.core.WorkingCopyOwner; |
| import org.eclipse.wst.jsdt.internal.core.DocumentContextFragmentRoot; |
| import org.eclipse.wst.jsdt.internal.core.Member; |
| import org.eclipse.wst.jsdt.internal.core.SourceRefElement; |
| import org.eclipse.wst.jsdt.web.core.internal.Logger; |
| import org.eclipse.wst.jsdt.web.core.internal.project.JsWebNature; |
| import org.eclipse.wst.sse.core.StructuredModelManager; |
| import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; |
| import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; |
| |
| /** |
| * |
| |
| * Provisional API: This class/interface is part of an interim API that is still under development and expected to |
| * change significantly before reaching stability. It is being made available at this early stage to solicit feedback |
| * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken |
| * (repeatedly) as the API evolves. |
| */ |
| public class JsTranslation implements IJsTranslation { |
| |
| private static final boolean DEBUG; |
| static { |
| String value = Platform.getDebugOption("org.eclipse.wst.jsdt.web.core/debug/jstranslation"); //$NON-NLS-1$ |
| DEBUG = value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$ |
| } |
| |
| private IJavaScriptUnit fCompilationUnit = null; |
| private DocumentContextFragmentRoot fDocumentScope; |
| private IJavaScriptProject fJavaProject = null; |
| private byte[] fLock = null; |
| private IProgressMonitor fProgressMonitor = null; |
| protected IStructuredDocument fHtmlDocument; |
| protected String fModelBaseLocation; |
| |
| |
| // private static final String SUPER_TYPE_NAME = "Window"; //$NON-NLS-1$ |
| // private static final String SUPER_TYPE_LIBRARY = "org.eclipse.wst.jsdt.launching.baseBrowserLibrary"; //$NON-NLS-1$ |
| |
| protected IJsTranslator fTranslator; |
| |
| private String mangledName; |
| protected boolean listenForChanges; |
| |
| public JsTranslation() { |
| /* do nothing */ |
| } |
| |
| public IJsTranslator getTranslator() { |
| if(fTranslator!=null) { |
| return fTranslator; |
| } |
| |
| fTranslator = new JsTranslator(fHtmlDocument, fModelBaseLocation, listenForChanges); |
| return this.fTranslator; |
| } |
| |
| |
| |
| protected JsTranslation(IStructuredDocument htmlDocument, IJavaScriptProject javaProj, boolean listenForChanges) { |
| fLock = new byte[0]; |
| fJavaProject = javaProj; |
| fHtmlDocument = htmlDocument; |
| setBaseLocation(); |
| mangledName = createMangledName(); |
| this.listenForChanges=listenForChanges; |
| } |
| |
| public IJsTranslation getInstance(IStructuredDocument htmlDocument, IJavaScriptProject javaProj, boolean listenForChanges) { |
| return new JsTranslation(htmlDocument,javaProj, listenForChanges); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#getJavaProject() |
| */ |
| public IJavaScriptProject getJavaProject() { |
| return fJavaProject; |
| } |
| |
| private IPackageFragmentRoot getDocScope(boolean reset) { |
| if (fDocumentScope == null) { |
| // IProject project = getJavaProject().getProject(); |
| // IResource absoluteRoot = |
| // ((IContainer)getJavaProject().getResource()).findMember( |
| // WebRootFinder.getWebContentFolder(fJavaProject.getProject())); |
| fDocumentScope = new DocumentContextFragmentRoot(fJavaProject, getFile(), WebRootFinder.getWebContentFolder(fJavaProject.getProject()), WebRootFinder.getServerContextRoot(fJavaProject.getProject()), JsWebNature.VIRTUAL_SCOPE_ENTRY); |
| fDocumentScope.setIncludedFiles(getTranslator().getRawImports()); |
| return fDocumentScope; |
| } |
| |
| if (reset) |
| fDocumentScope.setIncludedFiles(getTranslator().getRawImports()); |
| return fDocumentScope; |
| } |
| |
| private void setBaseLocation() { |
| IDOMModel xmlModel = null; |
| try { |
| xmlModel = (IDOMModel) StructuredModelManager.getModelManager().getExistingModelForRead(fHtmlDocument); |
| if (xmlModel == null) { |
| xmlModel = (IDOMModel) StructuredModelManager.getModelManager().getModelForRead(fHtmlDocument); |
| } |
| fModelBaseLocation = xmlModel.getBaseLocation(); |
| } |
| finally { |
| if (xmlModel != null) |
| xmlModel.releaseFromRead(); |
| } |
| // return xmlModel; |
| } |
| |
| public IFile getFile() { |
| return FileBuffers.getWorkspaceFileAtLocation(new Path(fModelBaseLocation)); |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#getHtmlDocument() |
| */ |
| public IDocument getHtmlDocument() { |
| return fHtmlDocument; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#getMissingTagStart() |
| */ |
| public int getMissingTagStart() { |
| return getTranslator().getMissingEndTagRegionStart(); |
| } |
| |
| private String getWebRoot() { |
| return WebRootFinder.getWebContentFolder(fJavaProject.getProject()).toString(); |
| } |
| |
| |
| public String getDirectoryUnderRoot() { |
| String webRoot = getWebRoot(); |
| IPath projectWebRootPath = getJavaProject().getPath().append(webRoot); |
| IPath filePath = new Path(fModelBaseLocation).removeLastSegments(1); |
| return filePath.removeFirstSegments(projectWebRootPath.matchingFirstSegments(filePath)).toString(); |
| } |
| |
| /** |
| * Originally from ReconcileStepForJava. Creates an IJavaScriptUnit from |
| * the contents of the JSP document. |
| * |
| * @return an IJavaScriptUnit from the contents of the JSP document |
| */ |
| private IJavaScriptUnit createCompilationUnit() throws JavaScriptModelException { |
| IPackageFragmentRoot root = getDocScope(true); |
| IJavaScriptUnit cu = root.getPackageFragment("").getJavaScriptUnit(getMangledName() + JsDataTypes.BASE_FILE_EXTENSION).getWorkingCopy(getWorkingCopyOwner(), getProblemRequestor(), getProgressMonitor()); //$NON-NLS-1$ |
| IBuffer buffer; |
| try { |
| buffer = cu.getBuffer(); |
| } |
| catch (JavaScriptModelException e) { |
| e.printStackTrace(); |
| buffer = null; |
| } |
| if (buffer != null) { |
| getTranslator().setBuffer(buffer); |
| } |
| return cu; |
| } |
| |
| public String fixupMangledName(String displayString) { |
| if (displayString == null) { |
| return null; |
| } |
| return displayString.replaceAll(getMangledName() + ".js", getHtmlPageName()); //$NON-NLS-1$ |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#getAllElementsInJsRange(int, int) |
| */ |
| public IJavaScriptElement[] getAllElementsInJsRange(int javaPositionStart, int javaPositionEnd) { |
| IJavaScriptElement[] EMTPY_RESULT_SET = new IJavaScriptElement[0]; |
| IJavaScriptElement[] result = EMTPY_RESULT_SET; |
| IJavaScriptElement[] allChildren = null; |
| try { |
| allChildren = getCompilationUnit().getChildren(); |
| } |
| catch (JavaScriptModelException e) { |
| } |
| Vector validChildren = new Vector(); |
| for (int i = 0; i < allChildren.length; i++) { |
| if (allChildren[i].getElementType() != IJavaScriptElement.PACKAGE_DECLARATION) { |
| ISourceRange range = getJSSourceRangeOf(allChildren[i]); |
| if (javaPositionStart <= range.getOffset() && range.getLength() + range.getOffset() <= (javaPositionEnd)) { |
| validChildren.add(allChildren[i]); |
| } |
| else if (allChildren[i].getElementType() == IJavaScriptElement.TYPE) { |
| validChildren.add(allChildren[i]); |
| } |
| } |
| } |
| if (validChildren.size() > 0) { |
| result = (IJavaScriptElement[]) validChildren.toArray(new IJavaScriptElement[]{}); |
| } |
| if (result == null || result.length == 0) { |
| return EMTPY_RESULT_SET; |
| } |
| return result; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#getCompilationUnit() |
| */ |
| public IJavaScriptUnit getCompilationUnit() { |
| // Genuitec Begin Fix 6149: Exception opening external HTML file |
| if (!getJavaProject().exists()) { |
| return null; |
| } |
| // Genuitec End Fix 6149: Exception opening external HTML file |
| synchronized (fLock) { |
| try { |
| if (fCompilationUnit == null) { |
| fCompilationUnit = createCompilationUnit(); |
| return fCompilationUnit; |
| } |
| |
| } |
| catch (JavaScriptModelException jme) { |
| if (JsTranslation.DEBUG) { |
| Logger.logException("error creating JSP working copy... ", jme); //$NON-NLS-1$ |
| } |
| } |
| |
| } |
| getDocScope(true); |
| try { |
| fCompilationUnit = fCompilationUnit.getWorkingCopy(getWorkingCopyOwner(), getProblemRequestor(), getProgressMonitor()); |
| // fCompilationUnit.makeConsistent(getProgressMonitor()); |
| } |
| catch (JavaScriptModelException ex) { |
| // TODO Auto-generated catch block |
| ex.printStackTrace(); |
| } |
| return fCompilationUnit; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#getElementsFromJsRange(int, int) |
| */ |
| public IJavaScriptElement[] getElementsFromJsRange(int javaPositionStart, int javaPositionEnd) { |
| IJavaScriptElement[] EMTPY_RESULT_SET = new IJavaScriptElement[0]; |
| IJavaScriptElement[] result = EMTPY_RESULT_SET; |
| try { |
| IJavaScriptUnit cu = getCompilationUnit(); |
| if (cu != null) { |
| synchronized (fLock) { |
| int cuDocLength = cu.getBuffer().getLength(); |
| int javaLength = javaPositionEnd - javaPositionStart; |
| if (cuDocLength > 0 && javaPositionStart >= 0 && javaLength >= 0 && javaPositionEnd <= cuDocLength) { |
| result = cu.codeSelect(javaPositionStart, javaLength, getWorkingCopyOwner()); |
| } |
| } |
| } |
| if (result == null || result.length == 0) { |
| return EMTPY_RESULT_SET; |
| } |
| } |
| catch (JavaScriptModelException x) { |
| Logger.logException(x); |
| } |
| return result; |
| } |
| |
| private String getHtmlPageName() { |
| IPath path = new Path(fModelBaseLocation); |
| return path.lastSegment(); |
| |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#getHtmlText() |
| */ |
| public String getHtmlText() { |
| return fHtmlDocument.get(); |
| } |
| |
| public String getJavaPath() { |
| IPath rootPath = new Path(fModelBaseLocation).removeLastSegments(1); |
| String cuPath = rootPath.append("/" + getMangledName() + JsDataTypes.BASE_FILE_EXTENSION).toString(); //$NON-NLS-1$ |
| return cuPath; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#getJsElementAtOffset(int) |
| */ |
| public IJavaScriptElement getJsElementAtOffset(int jsOffset) { |
| IJavaScriptElement elements = null; |
| try { |
| elements = getCompilationUnit().getElementAt(jsOffset); |
| } |
| catch (JavaScriptModelException e) { |
| // TODO Auto-generated catch block |
| if (JsTranslation.DEBUG) { |
| Logger.logException("error retrieving java elemtnt from compilation unit... ", e); //$NON-NLS-1$ |
| } |
| // } |
| } |
| return elements; |
| } |
| |
| private ISourceRange getJSSourceRangeOf(IJavaScriptElement element) { |
| // returns the offset in html of given element |
| ISourceRange range = null; |
| if (element instanceof Member) { |
| try { |
| range = ((Member) element).getNameRange(); |
| } catch (JavaScriptModelException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } |
| }else if (element instanceof SourceRefElement) { |
| try { |
| range = ((SourceRefElement) element).getSourceRange(); |
| } |
| catch (JavaScriptModelException e) { |
| e.printStackTrace(); |
| } |
| } |
| return range; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#getJsText() |
| */ |
| public String getJsText() { |
| return getTranslator().getJsText(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#getScriptPositions() |
| */ |
| public Position[] getScriptPositions() { |
| return getTranslator().getHtmlLocations(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#insertInFirstScriptRegion(java.lang.String) |
| */ |
| public void insertInFirstScriptRegion(String text) { |
| Position pos[] = getScriptPositions(); |
| int scriptStartOffset = 0; |
| if(pos!=null && pos.length>0) { |
| scriptStartOffset = pos[0].getOffset(); |
| |
| } |
| String insertText = (scriptStartOffset==0?"":"\n") + text; |
| insertScript(scriptStartOffset,insertText); |
| |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#insertScript(int, java.lang.String) |
| */ |
| public void insertScript(int offset, String text) { |
| |
| IDOMModel xmlModel = null; |
| Position[] inHtml = getScriptPositions(); |
| boolean isInsideExistingScriptRegion = false; |
| for (int i = 0; i < inHtml.length; i++) { |
| if (inHtml[i].overlapsWith(offset, 1)) { |
| // * inserting into a script region |
| isInsideExistingScriptRegion = true; |
| } |
| } |
| |
| String insertText = null; |
| |
| if (isInsideExistingScriptRegion) { |
| insertText = text; |
| } |
| else { |
| insertText = offset != 0 ? "\n" : "" + "<script type=\"text/javascript\">\n" + text + "\n</script>\n"; |
| } |
| // translator.documentAboutToBeChanged(null); |
| |
| synchronized (fLock) { |
| try { |
| xmlModel = (IDOMModel) StructuredModelManager.getModelManager().getExistingModelForEdit(fHtmlDocument); |
| if (xmlModel == null) { |
| xmlModel = (IDOMModel) StructuredModelManager.getModelManager().getModelForEdit(fHtmlDocument); |
| } |
| if (xmlModel != null) { |
| |
| |
| xmlModel.aboutToChangeModel(); |
| xmlModel.getDocument().getStructuredDocument().replaceText(this, offset, 0, insertText); |
| xmlModel.changedModel(); |
| try { |
| xmlModel.save(); |
| } |
| |
| catch (UnsupportedEncodingException e) {} |
| catch (IOException e) {} |
| catch (CoreException e) {} |
| } |
| } |
| finally { |
| if (xmlModel != null) |
| xmlModel.releaseFromEdit(); |
| } |
| } |
| |
| // translator.documentChanged(null); |
| |
| } |
| |
| public String getMangledName() { |
| return this.mangledName; |
| } |
| |
| private String createMangledName() { |
| return JsNameManglerUtil.mangle(fModelBaseLocation); |
| } |
| |
| /** |
| * |
| * @return the problem requestor for the JavaScriptUnit in this |
| * JSPTranslation |
| */ |
| private JsProblemRequestor getProblemRequestor() { |
| return CompilationUnitHelper.getInstance().getProblemRequestor(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#getProblems() |
| */ |
| public List getProblems() { |
| List problems = getProblemRequestor().getCollectedProblems(); |
| getProblemRequestor().endReporting(); |
| return problems != null ? problems : new ArrayList(); |
| } |
| |
| private IProgressMonitor getProgressMonitor() { |
| if (fProgressMonitor == null) { |
| fProgressMonitor = new NullProgressMonitor(); |
| } |
| return fProgressMonitor; |
| } |
| |
| public WorkingCopyOwner getWorkingCopyOwner() { |
| return CompilationUnitHelper.getInstance().getWorkingCopyOwner(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#ifOffsetInImportNode(int) |
| */ |
| public boolean ifOffsetInImportNode(int offset) { |
| Position[] importRanges = getTranslator().getImportHtmlRanges(); |
| for (int i = 0; i < importRanges.length; i++) { |
| if (importRanges[i].includes(offset)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#reconcileCompilationUnit() |
| */ |
| public void reconcileCompilationUnit() { |
| // if(true) return; |
| IJavaScriptUnit cu = getCompilationUnit(); |
| if (fCompilationUnit == null) { |
| return; |
| } |
| if (cu != null) { |
| try { |
| synchronized (fLock) { |
| // if(false) |
| // cu.makeConsistent(getProgressMonitor()); |
| cu.reconcile(IJavaScriptUnit.NO_AST, true, getWorkingCopyOwner(), getProgressMonitor()); |
| } |
| } |
| catch (JavaScriptModelException e) { |
| Logger.logException(e); |
| } |
| } |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#release() |
| */ |
| public void release() { |
| if (getTranslator() != null) |
| getTranslator().release(); |
| synchronized (fLock) { |
| if (fCompilationUnit != null) { |
| try { |
| if (JsTranslation.DEBUG) { |
| System.out.println("------------------------------------------------------------------"); //$NON-NLS-1$ |
| System.out.println("(-) JSPTranslation [" + this + "] discarding JavaScriptUnit: " + fCompilationUnit); //$NON-NLS-1$ //$NON-NLS-2$ |
| System.out.println("------------------------------------------------------------------"); //$NON-NLS-1$ |
| } |
| fCompilationUnit.discardWorkingCopy(); |
| } |
| catch (JavaScriptModelException e) { |
| // we're done w/ it anyway |
| } |
| } |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.web.core.internal.java.IJsTranslation#setProblemCollectingActive(boolean) |
| */ |
| public void setProblemCollectingActive(boolean collect) { |
| IJavaScriptUnit cu = getCompilationUnit(); |
| if (cu != null) { |
| getProblemRequestor().setIsActive(collect); |
| } |
| } |
| |
| public void classpathChange() { |
| |
| if (fDocumentScope != null) { |
| fDocumentScope.classpathChange(); |
| } |
| } |
| } |