package com.anjlab.eclipse.tapestry5; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import com.anjlab.eclipse.tapestry5.internal.CompilationUnitContext.CompilationUnitLifecycle; public class LocalTapestryContext extends TapestryContext { public LocalTapestryContext(IFile file) { super(); initFromFile(new LocalFile(this, file)); } public LocalTapestryContext(TapestryFile file) { super(); initFromFile(file); } @Override protected CompilationUnitLifecycle getCompilationUnit() { return new CompilationUnitLifecycle() { @Override public ICompilationUnit createCompilationUnit() { IFile javaFile = getJavaFileInternal(); if (javaFile == null) { return null; } return (ICompilationUnit) JavaCore.create(javaFile); } }; } private IFile getJavaFileInternal() { TapestryFile javaFile = getJavaFile(); return javaFile == null ? null : ((LocalFile)javaFile).getFile(); } @Override public String getPackageName() { IFile javaFile = getJavaFileInternal(); IContainer root = TapestryUtils.getRoot(javaFile); if (root != null) { return TapestryUtils.pathToPackageName(TapestryUtils.getRelativeFileName(javaFile.getParent(), root), false); } LocalFile localTemplateFile = (LocalFile) getTemplateFile(); if (localTemplateFile == null) { return null; } IFile templateFile = localTemplateFile.getFile(); root = TapestryUtils.getRoot(templateFile); if (root != null) { if (TapestryUtils.isWebApp(root)) { // Page from web context return TapestryUtils.getTapestryPackage(getProject(), "pages" + TapestryUtils.pathToPackageName(TapestryUtils.getRelativeFileName(templateFile.getParent(), root), true)); } return TapestryUtils.pathToPackageName(TapestryUtils.getRelativeFileName(templateFile.getParent(), root), false); } return null; } @Override public List<TapestryFile> findTapestryFiles(TapestryFile forFile, boolean findFirst, FileNameBuilder fileNameBuilder) { List<IFile> files = findTapestryFiles(((LocalFile) forFile).getFile(), findFirst, fileNameBuilder); List<TapestryFile> tapestryFiles = new ArrayList<TapestryFile>(); for (IFile file : files) { tapestryFiles.add(new LocalFile(this, file)); } return tapestryFiles; } @Override protected Map<String, String> codeDesignExtensionMappings() { Map<String, String> result = new HashMap<String, String>(); result.put("tml", "java"); result.put("java", "tml"); return result; } private List<IFile> findTapestryFiles(IFile forFile, boolean findFirst, FileNameBuilder fileNameBuilder) { try { String complementFileName = null; // Check if the file is in the web application context boolean fromWebapp = false; IProject project = forFile.getProject(); IContainer webapp = TapestryUtils.findWebapp(project); if (fromWebapp = EclipseUtils.isInFolder(forFile, webapp)) { if (isWebappContextAValidLocationForTheFile(forFile)) { String relativeFileName = TapestryUtils.getRelativeFileName(forFile, webapp); complementFileName = fileNameBuilder.getFileName( TapestryUtils.joinPath(TapestryUtils.getPagesPath(project), relativeFileName), forFile.getFileExtension()); } } List<IFile> resources = new ArrayList<IFile>(); if (!fromWebapp) { complementFileName = fileNameBuilder.getFileName(forFile.getName(), forFile.getFileExtension()); // Try searching in the same folder first resources = findMembers(forFile.getParent(), complementFileName); if (findFirst && !resources.isEmpty()) { return resources; } } // Look in the source folders IJavaProject javaProject = JavaCore.create(forFile.getProject()); IContainer container = null; if (javaProject.exists() && !fromWebapp) { IContainer adaptedProject = (IContainer) javaProject.getCorrespondingResource().getAdapter(IContainer.class); IResource adaptedFile = adaptedProject.findMember(forFile.getProjectRelativePath()); if (adaptedFile == null) { return resources; } container = adaptedFile.getParent(); while (container != null && !EclipseUtils.isSourceFolder(container)) { container = container.getParent(); } if (container != null) { if (StringUtils.isNotEmpty(complementFileName) && complementFileName.startsWith("/")) { findInSourceFolders(findFirst, complementFileName, resources, javaProject, container); if (findFirst && !resources.isEmpty()) { return resources; } } // Get the file name relative to source folder String relativeFileName = TapestryUtils.getRelativeFileName(forFile, container); complementFileName = fileNameBuilder.getFileName(relativeFileName, forFile.getFileExtension()); } } if (StringUtils.isEmpty(complementFileName)) { return Collections.emptyList(); } if (javaProject.exists()) { findInSourceFolders(findFirst, complementFileName, resources, javaProject, container); } if (findFirst && !resources.isEmpty()) { return resources; } // Look for TML files in web application context // https://github.com/anjlab/eclipse-tapestry5-plugin/issues/2 if (complementFileName.endsWith(".tml")) { if (webapp != null) { String pagesPath = TapestryUtils.getPagesPath(project); if (complementFileName.length() > pagesPath.length()) { IResource file = webapp.findMember(complementFileName.substring(pagesPath.length())); if (file instanceof IFile) { resources.add((IFile) file); } } } } return resources; } catch (CoreException e) { Activator.getDefault().logError("Error finding complement file", e); return Collections.emptyList(); } } private void findInSourceFolders(boolean findFirst, String complementFileName, List<IFile> resources, IJavaProject javaProject, IContainer container) throws JavaModelException { for (IPackageFragmentRoot root : javaProject.getAllPackageFragmentRoots()) { if (!EclipseUtils.isSourceFolder(root)) { continue; } IContainer resourceContainer = (IContainer) root.getCorrespondingResource().getAdapter(IContainer.class); if (container != null && resourceContainer.getFullPath().equals(container.getFullPath())) { continue; } List<IFile> resources2 = findMembers(resourceContainer, complementFileName); resources.addAll(resources2); if (findFirst && !resources.isEmpty()) { break; } } } private boolean isWebappContextAValidLocationForTheFile(IFile file) { return TapestryUtils.isTemplateFile(file.getProjectRelativePath()) || TapestryUtils.isStyleSheetFile(file.getProjectRelativePath()) || TapestryUtils.isJavaScriptFile(file.getProjectRelativePath()); } private List<IFile> findMembers(IContainer container, String path) { List<IFile> resources = new ArrayList<IFile>(); if (path.contains("*")) { // Find files by mask int slashIndex = path.lastIndexOf("/"); String parentPath = slashIndex < 0 ? "/" : path.substring(0, slashIndex); String mask = slashIndex < 0 ? path : path.substring(slashIndex + 1); Pattern pattern = Pattern.compile(mask); IResource resource = container.findMember(parentPath); if (resource instanceof IFolder) { try { IResource[] members = ((IFolder) resource).members(); for (IResource member : members) { if (pattern.matcher(member.getName()).matches()) { resources.add((IFile) member); } } } catch (CoreException e) { Activator.getDefault().logError("Error finding files by mask", e); } } } else { // Exact match IResource resource = container.findMember(path); if (resource != null && resource instanceof IFile) { resources.add((IFile) resource); } } return resources; } @Override public boolean isReadOnly() { return false; } private TapestryComponentSpecification specification; @Override public TapestryComponentSpecification getSpecification() { if (specification == null) { IType type = getJavaType(); if (type == null) { return TapestryComponentSpecification.EMPTY; } specification = new TapestryComponentSpecification(type, this); } return specification; } @Override public IType getJavaType() { TapestryFile javaFile = getJavaFile(); if (javaFile == null) { return null; } IFile file = ((LocalFile)javaFile).getFile(); ICompilationUnit compilationUnit = (ICompilationUnit) JavaCore.create(file); IType type = compilationUnit.findPrimaryType(); return type; } @Override public FileLookup createLookup() { return new LocalFileLookup(getJavaType()); } }