/*
* Copyright 2013 original Randori IntelliJ Plugin authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package randori.plugin.projectStructure.detection;
import java.io.*;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import org.jetbrains.annotations.NotNull;
import randori.compiler.bundle.IBundle;
import randori.compiler.bundle.IBundleLibrary;
import randori.compiler.bundle.io.BundleReader;
import randori.plugin.library.RandoriLibraryType;
import randori.plugin.module.RandoriModuleType;
import com.intellij.ide.util.DelegatingProgressIndicator;
import com.intellij.ide.util.importProject.ModuleDescriptor;
import com.intellij.ide.util.importProject.ModuleInsight;
import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot;
import com.intellij.lang.LanguageParserDefinitions;
import com.intellij.lang.javascript.JSTokenTypes;
import com.intellij.lang.javascript.JavaScriptSupportLoader;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Consumer;
import com.intellij.util.xml.NanoXmlUtil;
/**
* @author Frédéric THOMAS Date: 19/04/13 Time: 20:22
*/
class RandoriModuleInsight extends ModuleInsight
{
public RandoriModuleInsight(DelegatingProgressIndicator progress, Set<String> existingModuleNames,
Set<String> existingProjectLibraryNames)
{
super(progress, existingModuleNames, existingProjectLibraryNames);
}
@Override
protected ModuleDescriptor createModuleDescriptor(File moduleContentRoot,
Collection<DetectedProjectRoot> sourceRoots)
{
return new ModuleDescriptor(moduleContentRoot, RandoriModuleType.getInstance(), sourceRoots);
}
@Override
public boolean isApplicableRoot(DetectedProjectRoot root)
{
return root instanceof RandoriModuleSourceRoot;
}
@Override
protected boolean isSourceFile(File file)
{
return RandoriProjectStructureDetector.isRandoriSourceFile(file);
}
@Override
protected void scanSourceFileForImportedPackages(CharSequence chars, Consumer<String> result)
{
Lexer lexer = LanguageParserDefinitions.INSTANCE.forLanguage(JavaScriptSupportLoader.ECMA_SCRIPT_L4)
.createLexer(null);
lexer.start(chars);
if (RandoriProjectStructureDetector.readPackageName(chars, lexer) == null)
{
return;
}
while (true)
if ((lexer.getTokenType() != null) && (lexer.getTokenType() != JSTokenTypes.IMPORT_KEYWORD))
{
lexer.advance();
}
else
{
if (lexer.getTokenType() == null)
{
break;
}
lexer.advance();
RandoriProjectStructureDetector.skipWhiteSpaceAndComments(lexer);
String packageName = RandoriProjectStructureDetector.readQualifiedName(chars, lexer, true);
if (packageName != null)
{
String s = packageName.endsWith(".*") ? StringUtil.trimEnd(packageName, ".*") : StringUtil
.getPackageName(packageName);
if (!s.isEmpty())
result.consume(s);
}
}
}
@Override
protected boolean isLibraryFile(String fileName)
{
return fileName.toLowerCase().endsWith(".swc")
|| fileName.toLowerCase().endsWith(RandoriLibraryType.LIBRARY_DOT_EXTENSION);
}
@Override
protected void scanLibraryForDeclaredPackages(@NotNull final File file, final Consumer<String> result)
throws IOException
{
if (file.getName().toLowerCase().endsWith(RandoriLibraryType.LIBRARY_DOT_EXTENSION))
{
final Consumer<ZipInputStream> extractedSwcList = new Consumer<ZipInputStream>() {
@Override
public void consume(ZipInputStream swcZipInputStream)
{
try
{
scanSwcLibraryForDeclaredPackages(swcZipInputStream, result);
}
catch (IOException e)
{
//e.printStackTrace();
}
}
};
extractSwcFromRbl(file, extractedSwcList);
}
else
{
FileInputStream swcInputStream = null;
try
{
swcInputStream = new FileInputStream(file);
ZipInputStream swcZipInputStream = new ZipInputStream(swcInputStream);
scanSwcLibraryForDeclaredPackages(swcZipInputStream, result);
}
finally
{
if (swcInputStream != null)
try
{
swcInputStream.close();
}
catch (IOException ignored)
{
}
}
}
}
private void extractSwcFromRbl(File file, final Consumer<ZipInputStream> result) throws IOException
{
ZipFile zipFile = new ZipFile(file);
IBundle bundle = new BundleReader(file.getPath()).getBundle();
InputStream swcInputStream;
for (IBundleLibrary library : bundle.getLibraries())
{
swcInputStream = getSwcInputStream(zipFile, library.getName());
if (swcInputStream != null)
result.consume(new ZipInputStream(swcInputStream));
}
}
private static InputStream getSwcInputStream(ZipFile zipFile, String filename) throws IOException
{
ZipEntry zipEntry = null;
InputStream inputStream = null;
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements())
{
ZipEntry entry = entries.nextElement();
if (entry.getName().endsWith(filename + ".swc"))
{
zipEntry = entry;
break;
}
}
if (zipEntry != null)
inputStream = zipFile.getInputStream(zipEntry);
return inputStream;
}
private void scanSwcLibraryForDeclaredPackages(ZipInputStream swc, final Consumer<String> result)
throws IOException
{
ZipEntry e;
while ((e = swc.getNextEntry()) != null)
{
if ((!e.isDirectory()) && ("catalog.xml".equals(e.getName())))
{
InputStreamReader reader = new InputStreamReader(swc, "UTF-8");
NanoXmlUtil.parse(reader, new NanoXmlUtil.IXMLBuilderAdapter() {
private boolean processingDef;
public void startElement(String name, String nsPrefix, String nsURI, String systemID, int lineNr)
throws Exception
{
if (name.equals("def"))
this.processingDef = true;
}
public void endElement(String name, String nsPrefix, String nsURI) throws Exception
{
if (name.equals("def"))
this.processingDef = false;
}
public void addAttribute(String name, String nsPrefix, String nsURI, String value, String type)
throws Exception
{
if ((this.processingDef) && (name.equals("id")))
{
String fqn = value.replace(':', '.');
String packageName = StringUtil.getPackageName(fqn);
if (!packageName.isEmpty())
result.consume(packageName);
}
}
});
}
}
}
}