com.redhat.ceylon.cmr.impl.JSUtils Maven / Gradle / Ivy
/*
* Copyright 2011 Red Hat inc. and third party contributors as noted
* by the author tags.
* 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 com.redhat.ceylon.cmr.impl;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import net.minidev.json.JSONValue;
import com.redhat.ceylon.cmr.api.AbstractDependencyResolver;
import com.redhat.ceylon.cmr.api.ArtifactContext;
import com.redhat.ceylon.cmr.api.DependencyContext;
import com.redhat.ceylon.cmr.api.ModuleDependencyInfo;
import com.redhat.ceylon.cmr.api.ModuleInfo;
import com.redhat.ceylon.cmr.api.ModuleVersionArtifact;
import com.redhat.ceylon.cmr.api.ModuleVersionDetails;
import com.redhat.ceylon.cmr.api.Overrides;
import com.redhat.ceylon.cmr.spi.Node;
import com.redhat.ceylon.common.ModuleUtil;
import com.redhat.ceylon.model.cmr.ArtifactResult;
/**
* Utility functions to retrieve module meta information from compiled JS modules
*
* @author Tako Schotanus
*/
public final class JSUtils extends AbstractDependencyResolver implements ModuleInfoReader {
public static JSUtils INSTANCE = new JSUtils();
private JSUtils() {
}
@Override
public ModuleInfo resolve(DependencyContext context, Overrides overrides) {
if (context.ignoreInner()) {
return null;
}
ArtifactResult result = context.result();
File mod = result.artifact();
if (mod != null && (mod.getName().toLowerCase().endsWith(ArtifactContext.JS_MODEL)
|| mod.getName().toLowerCase().endsWith(ArtifactContext.JS))) {
return readModuleInformation(result.name(), mod, overrides);
} else {
return null;
}
}
@Override
public ModuleInfo resolveFromFile(File file, String name, String version, Overrides overrides) {
throw new UnsupportedOperationException("Operation not supported for .js files");
}
@Override
public ModuleInfo resolveFromInputStream(InputStream stream, String name, String version, Overrides overrides) {
throw new UnsupportedOperationException("Operation not supported for .js files");
}
public Node descriptor(Node artifact) {
return null; // artifact is a descriptor
}
/**
* Read module info from JS file
*
* @param moduleName the module name
* @param jarFile the module JS file
* @return module info list
*/
public static ModuleInfo readModuleInformation(final String moduleName, final File jarFile, Overrides overrides) {
Map model = loadJsonModel(jarFile);
String version = asString(metaModelProperty(model, "$mod-version"));
return getModuleInfo(model, moduleName, version, overrides);
}
@Override
public int[] getBinaryVersions(String moduleName, String version, File moduleArchive) {
int major = 0;
int minor = 0;
ModuleVersionDetails mvd = readModuleInfo(moduleName, version, moduleArchive, false, null);
ModuleVersionArtifact mva = mvd.getArtifactTypes().first();
if (mva.getMajorBinaryVersion() != null) {
major = mva.getMajorBinaryVersion();
}
if (mva.getMinorBinaryVersion() != null) {
minor = mva.getMinorBinaryVersion();
}
return new int[]{major, minor};
}
private static ScriptEngine getEngine(File moduleArchive) {
ScriptEngine engine;
try {
engine = new ScriptEngineManager().getEngineByName("JavaScript");
engine.eval("var exports={}");
engine.eval("var module={}");
engine.eval("function require() { return { '$addmod$' : function() {} } }");
engine.eval(new FileReader(moduleArchive));
return engine;
} catch (Exception ex) {
throw new RuntimeException("Failed to parse module JS file", ex);
}
}
private static ModuleInfo getModuleInfo(Map model, String module, String version, Overrides overrides) {
try {
return getModuleInfo(metaModelProperty(model, "$mod-deps"), module, version, overrides);
} catch (Exception ex) {
throw new RuntimeException("Failed to parse module JS file", ex);
}
}
@Override
public ModuleVersionDetails readModuleInfo(String moduleName, String moduleVersion, File moduleArchive, boolean includeMembers, Overrides overrides) {
Map model = loadJsonModel(moduleArchive);
String name = asString(metaModelProperty(model, "$mod-name"));
if (!moduleName.equals(name)) {
throw new RuntimeException("Incorrect module");
}
String version = asString(metaModelProperty(model, "$mod-version"));
Set dependencies = getModuleInfo(model, moduleName, version, overrides).getDependencies();
String type = ArtifactContext.getSuffixFromFilename(moduleArchive.getName());
Integer major = null, minor = null;
String bin = asString(metaModelProperty(model, "$mod-bin"));
if (bin != null) {
int p = bin.indexOf('.');
if (p >= 0) {
major = Integer.parseInt(bin.substring(0, p));
minor = Integer.parseInt(bin.substring(p + 1));
} else {
major = Integer.parseInt(bin);
}
}
ModuleVersionDetails mvd = new ModuleVersionDetails(moduleName, version);
mvd.getArtifactTypes().add(new ModuleVersionArtifact(type, major, minor));
mvd.getDependencies().addAll(dependencies);
Map annotations = (Map) metaModelProperty(model, "$mod-anns");
if(annotations != null){
mvd.setDoc(asString(annotations.get("doc")));
mvd.setLicense(asString(annotations.get("license")));
Iterable by = (Iterable) annotations.get("by");
if(by != null){
for(String author : by){
mvd.getAuthors().add(author);
}
}
}
if (includeMembers) {
mvd.setMembers(getMembers(moduleName, moduleArchive));
}
return mvd;
}
private Set getMembers(String moduleName, File moduleArchive) {
// TODO Implement this!
throw new RuntimeException("Not implemented yet");
}
private static Object metaModelProperty(Map model, String propName) {
return model.get(propName);
}
private static String asString(Object obj) {
if (obj == null) {
return null;
} else if(obj instanceof Iterable){
Iterator iter = ((Iterable) obj).iterator();
return iter.hasNext() ? iter.next() : null;
} else {
return obj.toString();
}
}
private static ModuleInfo getModuleInfo(Object obj, String moduleName, String version, Overrides overrides) {
if (obj == null) {
return new ModuleInfo(null, Collections.emptySet());
}
if (!(obj instanceof Iterable)) {
throw new RuntimeException("Expected something Iterable");
}
@SuppressWarnings("unchecked")
Iterable
© 2015 - 2024 Weber Informatics LLC | Privacy Policy