package org.osmorc.facet; import com.intellij.facet.FacetType; import com.intellij.framework.detection.FacetBasedFrameworkDetector; import com.intellij.framework.detection.FileContentPattern; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.patterns.ElementPattern; import com.intellij.patterns.PatternCondition; import com.intellij.util.ProcessingContext; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.indexing.FileContent; import org.jetbrains.annotations.NotNull; import org.osgi.framework.Constants; import org.osmorc.manifest.ManifestFileTypeFactory; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.*; /** * @author nik */ public class OsmorcFrameworkDetector extends FacetBasedFrameworkDetector<OsmorcFacet, OsmorcFacetConfiguration> { private final Logger logger = Logger.getInstance("#org.osmorc.facet.OsmorcFrameworkDetector"); private final String[] DETECTION_HEADERS = {Constants.BUNDLE_SYMBOLICNAME}; public OsmorcFrameworkDetector() { super("osmorc"); } @Override public FacetType<OsmorcFacet, OsmorcFacetConfiguration> getFacetType() { return OsmorcFacetType.getInstance(); } @Override protected OsmorcFacetConfiguration createConfiguration(Collection<VirtualFile> files) { OsmorcFacetConfiguration osmorcFacetConfiguration = getFacetType().createDefaultConfiguration(); osmorcFacetConfiguration.setOsmorcControlsManifest(false); osmorcFacetConfiguration.setManifestLocation(ContainerUtil.getFirstItem(files).getPath()); osmorcFacetConfiguration.setUseProjectDefaultManifestFileLocation(false); return osmorcFacetConfiguration; } @Override public void setupFacet(@NotNull OsmorcFacet facet, ModifiableRootModel model) { VirtualFile[] contentRoots = model.getContentRoots(); OsmorcFacetConfiguration osmorcFacetConfiguration = facet.getConfiguration(); VirtualFile manifestFile = LocalFileSystem.getInstance().findFileByPath(osmorcFacetConfiguration.getManifestLocation()); if (manifestFile != null) { for (VirtualFile contentRoot : contentRoots) { if (VfsUtil.isAncestor(contentRoot, manifestFile, false)) { // IDEADEV-40357 osmorcFacetConfiguration.setManifestLocation(VfsUtilCore.getRelativePath(manifestFile, contentRoot, '/')); break; } } } else { osmorcFacetConfiguration.setManifestLocation(""); osmorcFacetConfiguration.setUseProjectDefaultManifestFileLocation(true); } String manifestFileName = osmorcFacetConfiguration.getManifestLocation(); if (manifestFileName.endsWith("template.mf")) { // this is a bundlor manifest template, so make the facet do bundlor osmorcFacetConfiguration.setManifestLocation(""); osmorcFacetConfiguration.setBundlorFileLocation(manifestFileName); osmorcFacetConfiguration.setUseBundlorFile(true); } } @NotNull @Override public ElementPattern<FileContent> createSuitableFilePattern() { return FileContentPattern.fileContent().with(new PatternCondition<FileContent>("osmorc manifest file") { @Override public boolean accepts(@NotNull FileContent content, ProcessingContext context) { return isSuitableFile(content.getFile()); } }); } @NotNull @Override public FileType getFileType() { return ManifestFileTypeFactory.MANIFEST; } private boolean isSuitableFile(VirtualFile file) { List<String> headersToDetect = new ArrayList<String>(Arrays.asList(DETECTION_HEADERS)); if (file != null && file.exists() && !file.isDirectory()) { BufferedReader bufferedReader = null; try { InputStream inputStream = file.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); bufferedReader = new BufferedReader(inputStreamReader); String line; while ((line = bufferedReader.readLine()) != null && headersToDetect.size() > 0) { for (Iterator<String> headersToDetectIterator = headersToDetect.iterator(); headersToDetectIterator.hasNext();) { String headerToDetect = headersToDetectIterator.next(); if (line.startsWith(headerToDetect)) { headersToDetectIterator.remove(); break; } } } } catch (IOException e) { // this should fix IDEA-17977 (EA reported exception). logger.warn("There was an unexpected exception when accessing " + file.getName() + " (" + e.getMessage() + ")"); return false; } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException e) { logger.warn("There was an unexpected exception when closing stream to " + file.getName() + " (" + e.getMessage() + ")"); return false; } } } } return headersToDetect.size() == 0; } }