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.vfs.*; 025 import com.intellij.psi.PsiFile; 026 import com.intellij.psi.PsiManager; 027 import org.jetbrains.annotations.NotNull; 028 import org.jetbrains.jet.lang.psi.JetFile; 029 import org.jetbrains.k2js.utils.JetFileUtils; 030 031 import java.io.IOException; 032 import java.io.InputStream; 033 import java.util.ArrayList; 034 import java.util.Collections; 035 import java.util.Enumeration; 036 import java.util.List; 037 import java.util.zip.ZipEntry; 038 import java.util.zip.ZipFile; 039 040 public class LibrarySourcesConfig extends Config { 041 @NotNull 042 public static final Key<String> EXTERNAL_MODULE_NAME = Key.create("externalModule"); 043 @NotNull 044 public static final String UNKNOWN_EXTERNAL_MODULE_NAME = "<unknown>"; 045 046 @NotNull 047 private static final Logger LOG = Logger.getInstance("#org.jetbrains.k2js.config.LibrarySourcesConfig"); 048 049 @NotNull 050 private final List<String> files; 051 052 public LibrarySourcesConfig( 053 @NotNull Project project, 054 @NotNull String moduleId, 055 @NotNull List<String> files, 056 @NotNull EcmaVersion ecmaVersion, 057 boolean sourcemap 058 ) { 059 super(project, moduleId, ecmaVersion, sourcemap); 060 this.files = files; 061 } 062 063 @NotNull 064 @Override 065 protected List<JetFile> generateLibFiles() { 066 if (files.isEmpty()) { 067 return Collections.emptyList(); 068 } 069 070 List<JetFile> jetFiles = new ArrayList<JetFile>(); 071 String moduleName = UNKNOWN_EXTERNAL_MODULE_NAME; 072 VirtualFileSystem fileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL); 073 PsiManager psiManager = PsiManager.getInstance(getProject()); 074 075 for (String path : files) { 076 if (path.charAt(0) == '@') { 077 moduleName = path.substring(1); 078 } 079 else if (path.endsWith(".jar") || path.endsWith(".zip")) { 080 try { 081 jetFiles.addAll(readZip(path)); 082 } 083 catch (IOException e) { 084 LOG.error(e); 085 } 086 } 087 else { 088 VirtualFile file = fileSystem.findFileByPath(path); 089 if (file == null) { 090 LOG.error("File '" + path + "not found.'"); 091 } 092 else if (file.isDirectory()) { 093 JetFileCollector jetFileCollector = new JetFileCollector(jetFiles, moduleName, psiManager); 094 VfsUtilCore.visitChildrenRecursively(file, jetFileCollector); 095 } 096 else { 097 jetFiles.add(getJetFileByVirtualFile(file, moduleName, psiManager)); 098 } 099 } 100 } 101 102 return jetFiles; 103 } 104 105 private List<JetFile> readZip(String file) throws IOException { 106 ZipFile zipFile = new ZipFile(file); 107 try { 108 return traverseArchive(zipFile); 109 } 110 finally { 111 zipFile.close(); 112 } 113 } 114 115 @NotNull 116 private List<JetFile> traverseArchive(@NotNull ZipFile file) throws IOException { 117 List<JetFile> result = Lists.newArrayList(); 118 Enumeration<? extends ZipEntry> zipEntries = file.entries(); 119 while (zipEntries.hasMoreElements()) { 120 ZipEntry entry = zipEntries.nextElement(); 121 if (!entry.isDirectory() && entry.getName().endsWith(".kt")) { 122 InputStream stream = file.getInputStream(entry); 123 String text = FileUtil.loadTextAndClose(stream); 124 JetFile jetFile = JetFileUtils.createJetFile(entry.getName(), text, getProject()); 125 jetFile.putUserData(EXTERNAL_MODULE_NAME, UNKNOWN_EXTERNAL_MODULE_NAME); 126 result.add(jetFile); 127 } 128 } 129 return result; 130 } 131 132 private static JetFile getJetFileByVirtualFile(VirtualFile file, String moduleName, PsiManager psiManager) { 133 PsiFile psiFile = psiManager.findFile(file); 134 assert psiFile != null; 135 psiFile.putUserData(EXTERNAL_MODULE_NAME, moduleName); 136 return (JetFile) psiFile; 137 } 138 139 private static class JetFileCollector extends VirtualFileVisitor { 140 private final List<JetFile> jetFiles; 141 private final String moduleName; 142 private final PsiManager psiManager; 143 144 private JetFileCollector(List<JetFile> files, String name, PsiManager manager) { 145 moduleName = name; 146 psiManager = manager; 147 jetFiles = files; 148 } 149 150 @Override 151 public boolean visitFile(@NotNull VirtualFile file) { 152 if (file.getName().endsWith(".kt")) { 153 jetFiles.add(getJetFileByVirtualFile(file, moduleName, psiManager)); 154 return false; 155 } 156 return true; 157 } 158 } 159 }