Skip to content

Commit

Permalink
Provide extension point to install external modules. See
Browse files Browse the repository at this point in the history
  • Loading branch information
angelozerr committed Sep 15, 2015
1 parent d19bf95 commit d7ceb47
Show file tree
Hide file tree
Showing 25 changed files with 647 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import java.io.File;
import java.io.IOException;

import tern.utils.UnZip;
import tern.utils.ZipUtils;

public class PathHelper {

Expand Down Expand Up @@ -76,7 +76,7 @@ private static void unZipIfNecessary(String os, String ws, String arch) {

File zipFile = new File(folderName+".zip");
try {
UnZip.extract(zipFile,zipFile.getParentFile());
ZipUtils.extract(zipFile,zipFile.getParentFile());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Expand Down
12 changes: 12 additions & 0 deletions core/tern.core/src/tern/repository/ITernRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package tern.repository;

import java.io.File;
import java.io.IOException;

import tern.TernException;
import tern.server.ITernModule;
Expand Down Expand Up @@ -111,4 +112,15 @@ public interface ITernRepository {
* @return the list fo tern plugin which are linter.
*/
ITernPlugin[] getLinters();

/**
* Install the given module file to the repository.
*
* @param moduleFile
* module file which is a zip/jar or folder which contains tern
* module.
* @throws IOException
* @throws TernException
*/
void install(File moduleFile) throws IOException, TernException;
}
72 changes: 48 additions & 24 deletions core/tern.core/src/tern/repository/TernRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package tern.repository;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand All @@ -24,6 +25,7 @@
import tern.server.ModuleType;
import tern.utils.ExtensionUtils;
import tern.utils.TernModuleHelper;
import tern.utils.ZipUtils;

/**
* Tern repository implementation.
Expand All @@ -33,9 +35,10 @@ public class TernRepository implements ITernRepository {

private static final String DEFS_FOLDER = "defs";
private static final String PLUGIN_FOLDER = "plugin";
private static final String NODE_MODULES_FOLDER = "..";
private static final List<String> IGNORE_PLUGINS = Arrays.asList(new String[]{"commonjs", "modules", "node_resolve"});


private static final List<String> IGNORE_PLUGINS = Arrays
.asList(new String[] { "commonjs", "modules", "node_resolve" });

private final String name;
private File ternBaseDir;
private final boolean defaultRepository;
Expand Down Expand Up @@ -83,7 +86,7 @@ public ITernModule getModuleByOrigin(String origin) {
return null;
}
}

private void intializeIfNeeded() throws TernException {
if (modules == null) {
Map<String, ITernModule> modules = new HashMap<String, ITernModule>();
Expand All @@ -98,29 +101,29 @@ private void intializeIfNeeded() throws TernException {
private ITernPlugin[] searchLinters(Collection<ITernModule> values) {
Collection<ITernPlugin> linters = new ArrayList<ITernPlugin>();
for (ITernModule module : values) {
if (module.getModuleType() == ModuleType.Plugin
&& ((ITernPlugin) module).isLinter()) {
if (module.getModuleType() == ModuleType.Plugin && ((ITernPlugin) module).isLinter()) {
linters.add((ITernPlugin) module);
}
}
return linters.toArray(ITernPlugin.EMPTY_PLUGIN);
}

private void loadModules(
Map<String, ITernModule> modules,
Map<String, ITernModule> modulesByOrigin) throws TernException {
private void loadModules(Map<String, ITernModule> modules, Map<String, ITernModule> modulesByOrigin)
throws TernException {
// defs
loadModules(modules, modulesByOrigin, DEFS_FOLDER, null);
loadModules(modules, modulesByOrigin, new File(getTernBaseDir(), DEFS_FOLDER), null);
// plugin
loadModules(modules, modulesByOrigin, PLUGIN_FOLDER, IGNORE_PLUGINS);
loadModules(modules, modulesByOrigin, new File(getTernBaseDir(), PLUGIN_FOLDER), IGNORE_PLUGINS);
// node_modules
loadModules(modules, modulesByOrigin, NODE_MODULES_FOLDER, null);
loadModules(modules, modulesByOrigin, getNodeModulesDir(), null);
}

private void loadModules(Map<String, ITernModule> modules,
Map<String, ITernModule> modulesByOrigin, String dir, List<String> ignoreModules)
throws TernException {
File baseDir = new File(getTernBaseDir(), dir);
private File getNodeModulesDir() {
return getTernBaseDir().getParentFile();
}

private void loadModules(Map<String, ITernModule> modules, Map<String, ITernModule> modulesByOrigin, File baseDir,
List<String> ignoreModules) throws TernException {
if (baseDir.exists()) {
File[] files = baseDir.listFiles();
File file = null;
Expand Down Expand Up @@ -176,21 +179,18 @@ public File getFile(ITernModule module) {
switch (module.getModuleType()) {
case Plugin:
case Configurable:
moduleFile = new File(ternBaseDir, new StringBuilder(PLUGIN_FOLDER)
.append('/').append(fileName).toString());
moduleFile = new File(ternBaseDir,
new StringBuilder(PLUGIN_FOLDER).append('/').append(fileName).toString());
break;
case Def:
moduleFile = new File(ternBaseDir, new StringBuilder(DEFS_FOLDER)
.append('/').append(fileName).toString());
moduleFile = new File(ternBaseDir, new StringBuilder(DEFS_FOLDER).append('/').append(fileName).toString());
break;
}
if (moduleFile.exists()) {
return moduleFile;
}
moduleFile = new File(ternBaseDir, new StringBuilder(
NODE_MODULES_FOLDER).append('/')
.append(ExtensionUtils.TERN_SUFFIX).append(module.getName())
.append('/').append(fileName).toString());
moduleFile = new File(getNodeModulesDir(), new StringBuilder(ExtensionUtils.TERN_SUFFIX)
.append(module.getName()).append('/').append(fileName).toString());
if (moduleFile.exists()) {
return moduleFile;
}
Expand All @@ -207,4 +207,28 @@ public ITernPlugin[] getLinters() {
}
return linters;
}

@Override
public void install(File moduleFile) throws IOException, TernException {
if (!moduleFile.exists()) {
throw new TernException(
"Cannot install module file <" + TernModuleHelper.getPath(moduleFile) + ">. It doesn't exists.");
}
File baseDir = getNodeModulesDir();
if (!baseDir.exists()) {
throw new TernException("Cannot install module file <" + TernModuleHelper.getPath(moduleFile)
+ ">. Tern repository <" + TernModuleHelper.getPath(baseDir) + "> doesn't exists.");
}
if (ZipUtils.isZipFile(moduleFile) || ZipUtils.isJarFile(moduleFile)) {
// Zip or JAR file, unzip it to the tern repository.
ZipUtils.extract(moduleFile, baseDir);
} else if (moduleFile.isDirectory()) {
// Folder, copy this folder to the tern repository
throw new TernException("TODO!");
} else {
throw new TernException("Cannot install module file <" + TernModuleHelper.getPath(moduleFile)
+ ">. It must be a folder or a zip/jar file.");
}

}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2013-2014 Angelo ZERR.
* Copyright (c) 2013-2015 Angelo ZERR.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
Expand All @@ -18,15 +18,43 @@
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class UnZip {
/**
* Zip Utilities.
*
*/
public class ZipUtils {

private static final String ZIP_EXTENSION = ".zip";
private static final String JAR_EXTENSION = ".jar";
private static final String BIN_FOLDER = "/bin";

/**
* Returns true if the given file is a zip file and false otherwise.
*
* @param file
* @return true if the given file is a zip file and false otherwise.
*/
public static boolean isZipFile(File file) {
return file.isFile() && file.getName().endsWith(ZIP_EXTENSION);
}

/**
* Returns true if the given file is a jar file and false otherwise.
*
* @param file
* @return true if the given file is a jar file and false otherwise.
*/
public static boolean isJarFile(File file) {
return file.isFile() && file.getName().endsWith(JAR_EXTENSION);
}

/**
* Extract zip file to destination folder.
*
* @param file
* zip file to extract
* @param destination
* destinatin folder
* destination folder
*/
public static void extract(File file, File destination) throws IOException {
ZipInputStream in = null;
Expand All @@ -46,6 +74,12 @@ public static void extract(File file, File destination) throws IOException {
if (entry.isDirectory()) {
extracted.mkdirs();
} else {
// Be sure that parent file exists
File baseDir = extracted.getParentFile();
if (!baseDir.exists()) {
baseDir.mkdirs();
}

out = new FileOutputStream(extracted);

// Transfer bytes from the ZIP file to the output file
Expand All @@ -58,7 +92,7 @@ public static void extract(File file, File destination) throws IOException {

// Close the stream
out.close();
if (extracted.getParent().contains("/bin")) {
if (extracted.getParent().contains(BIN_FOLDER)) {
extracted.setExecutable(true);
}
}
Expand Down
3 changes: 2 additions & 1 deletion eclipse/tern.eclipse.ide.core/plugin.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ ternConsoleConnectors.name=Tern Console Connectors
ternFileConfigurations.name=Tern File Configurations
ternNatureAdapters.name=Tern Nature Adapters
ternProjectLifecycleListeners.name=Tern project lifecycle listeners
ternServerTypes.name=Tern Server Types
ternServerTypes.name=Tern Server Types
ternModuleInstalls.name=Tern module installation
2 changes: 2 additions & 0 deletions eclipse/tern.eclipse.ide.core/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
schema="schema/ternProjectLifecycleListeners.exsd" />
<extension-point id="ternServerTypes" name="%ternServerTypes.name"
schema="schema/ternServerTypes.exsd" />
<extension-point id="ternModuleInstalls" name="%ternModuleInstalls.name"
schema="schema/ternModuleInstalls.exsd" />

<!-- Preferences initialization -->
<extension
Expand Down
99 changes: 99 additions & 0 deletions eclipse/tern.eclipse.ide.core/schema/ternModuleInstalls.exsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="tern.eclipse.ide.core" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appInfo>
<meta.schema plugin="tern.eclipse.ide.core" id="ternModuleInstalls" name="Tern Module Installs"/>
</appInfo>
<documentation>
Extension point for provide Tern module Installs.
</documentation>
</annotation>

<element name="extension">
<annotation>
<appInfo>
<meta.element />
</appInfo>
</annotation>
<complexType>
<sequence minOccurs="1" maxOccurs="unbounded">
<element ref="moduleInstall" minOccurs="1" maxOccurs="unbounded"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
a fully-qualified name of the target extension point
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
an optional id
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
an optional name
</documentation>
</annotation>
</attribute>
</complexType>
</element>

<element name="moduleInstall">
<complexType>
<sequence>
</sequence>
<attribute name="id" type="string" use="required">
<annotation>
<documentation>

</documentation>
</annotation>
</attribute>
<attribute name="name" type="string" use="required">
<annotation>
<documentation>

</documentation>
</annotation>
</attribute>
<attribute name="src" type="string" use="required">
<annotation>
<documentation>

</documentation>
<appInfo>
<meta.attribute kind="resource"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>

<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
2.0
</documentation>
</annotation>



<annotation>
<appInfo>
<meta.section type="implementation"/>
</appInfo>
<documentation>
This plugin itself does not have any predefined builders.
</documentation>
</annotation>


</schema>
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import tern.TernResourcesManager;
import tern.eclipse.ide.internal.core.TernFileConfigurationManager;
import tern.eclipse.ide.internal.core.TernModuleInstallManager;
import tern.eclipse.ide.internal.core.TernNatureAdaptersManager;
import tern.eclipse.ide.internal.core.TernProjectLifecycleManager;
import tern.eclipse.ide.internal.core.TernRepositoryManager;
Expand Down Expand Up @@ -62,7 +63,8 @@ public void start(BundleContext context) throws Exception {
IDETernProjectSynchronizer.getInstance().initialize();
TernModuleMetadataManager.getInstance().init(getTernCoreBaseDir());
TernFileConfigurationManager.getManager().initialize();

TernModuleInstallManager.getManager().initialize();

// set up resource management for IDE
InternalTernResourcesManager resMan = InternalTernResourcesManager
.getInstance();
Expand Down Expand Up @@ -90,7 +92,8 @@ public void stop(BundleContext context) throws Exception {
TernNatureAdaptersManager.getManager().destroy();
TernFileConfigurationManager.getManager().destroy();
IDETernProjectSynchronizer.getInstance().dispose();

TernModuleInstallManager.getManager().destroy();

plugin = null;
super.stop(context);
}
Expand Down
Loading

0 comments on commit d7ceb47

Please sign in to comment.