001 /* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.k2js.config; 018 019 import com.google.common.collect.Lists; 020 import com.intellij.openapi.diagnostic.Logger; 021 import com.intellij.openapi.project.Project; 022 import com.intellij.openapi.util.Key; 023 import com.intellij.openapi.util.io.FileUtil; 024 import com.intellij.openapi.util.text.StringUtil; 025 import com.intellij.openapi.vfs.*; 026 import com.intellij.psi.PsiFile; 027 import com.intellij.psi.PsiManager; 028 import org.jetbrains.annotations.NotNull; 029 import org.jetbrains.jet.lang.psi.JetFile; 030 import org.jetbrains.jet.lang.psi.JetPsiFactory; 031 032 import java.io.IOException; 033 import java.io.InputStream; 034 import java.util.ArrayList; 035 import java.util.Collections; 036 import java.util.Enumeration; 037 import java.util.List; 038 import java.util.zip.ZipEntry; 039 import java.util.zip.ZipFile; 040 041 public class LibrarySourcesConfig extends Config { 042 @NotNull 043 public static final Key<String> EXTERNAL_MODULE_NAME = Key.create("externalModule"); 044 @NotNull 045 public static final String UNKNOWN_EXTERNAL_MODULE_NAME = "<unknown>"; 046 047 @NotNull 048 private static final Logger LOG = Logger.getInstance("#org.jetbrains.k2js.config.LibrarySourcesConfig"); 049 050 @NotNull 051 private final List<String> files; 052 053 public LibrarySourcesConfig( 054 @NotNull Project project, 055 @NotNull String moduleId, 056 @NotNull List<String> files, 057 @NotNull EcmaVersion ecmaVersion, 058 boolean sourcemap 059 ) { 060 super(project, moduleId, ecmaVersion, sourcemap); 061 this.files = files; 062 } 063 064 @NotNull 065 @Override 066 protected List<JetFile> generateLibFiles() { 067 if (files.isEmpty()) { 068 return Collections.emptyList(); 069 } 070 071 List<JetFile> jetFiles = new ArrayList<JetFile>(); 072 String moduleName = UNKNOWN_EXTERNAL_MODULE_NAME; 073 VirtualFileSystem fileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL); 074 PsiManager psiManager = PsiManager.getInstance(getProject()); 075 076 for (String path : files) { 077 if (path.charAt(0) == '@') { 078 moduleName = path.substring(1); 079 } 080 else if (path.endsWith(".jar") || path.endsWith(".zip")) { 081 try { 082 jetFiles.addAll(readZip(path)); 083 } 084 catch (IOException e) { 085 LOG.error(e); 086 } 087 } 088 else { 089 VirtualFile file = fileSystem.findFileByPath(path); 090 if (file == null) { 091 LOG.error("File '" + path + "not found.'"); 092 } 093 else if (file.isDirectory()) { 094 JetFileCollector jetFileCollector = new JetFileCollector(jetFiles, moduleName, psiManager); 095 VfsUtilCore.visitChildrenRecursively(file, jetFileCollector); 096 } 097 else { 098 jetFiles.add(getJetFileByVirtualFile(file, moduleName, psiManager)); 099 } 100 } 101 } 102 103 return jetFiles; 104 } 105 106 private List<JetFile> readZip(String file) throws IOException { 107 ZipFile zipFile = new ZipFile(file); 108 try { 109 return traverseArchive(zipFile); 110 } 111 finally { 112 zipFile.close(); 113 } 114 } 115 116 @NotNull 117 private List<JetFile> traverseArchive(@NotNull ZipFile file) throws IOException { 118 List<JetFile> result = Lists.newArrayList(); 119 Enumeration<? extends ZipEntry> zipEntries = file.entries(); 120 while (zipEntries.hasMoreElements()) { 121 ZipEntry entry = zipEntries.nextElement(); 122 if (!entry.isDirectory() && entry.getName().endsWith(".kt")) { 123 InputStream stream = file.getInputStream(entry); 124 String text = StringUtil.convertLineSeparators(FileUtil.loadTextAndClose(stream)); 125 JetFile jetFile = JetPsiFactory.createFile(getProject(), entry.getName(), text); 126 jetFile.putUserData(EXTERNAL_MODULE_NAME, UNKNOWN_EXTERNAL_MODULE_NAME); 127 result.add(jetFile); 128 } 129 } 130 return result; 131 } 132 133 private static JetFile getJetFileByVirtualFile(VirtualFile file, String moduleName, PsiManager psiManager) { 134 PsiFile psiFile = psiManager.findFile(file); 135 assert psiFile != null; 136 psiFile.putUserData(EXTERNAL_MODULE_NAME, moduleName); 137 return (JetFile) psiFile; 138 } 139 140 private static class JetFileCollector extends VirtualFileVisitor { 141 private final List<JetFile> jetFiles; 142 private final String moduleName; 143 private final PsiManager psiManager; 144 145 private JetFileCollector(List<JetFile> files, String name, PsiManager manager) { 146 moduleName = name; 147 psiManager = manager; 148 jetFiles = files; 149 } 150 151 @Override 152 public boolean visitFile(@NotNull VirtualFile file) { 153 if (file.getName().endsWith(".kt")) { 154 jetFiles.add(getJetFileByVirtualFile(file, moduleName, psiManager)); 155 return false; 156 } 157 return true; 158 } 159 } 160 }