blob: 54d197c38130d3f3c0037f4a2f5bedfe751d2aa2 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.netbeans.modules.javascript2.nodejs.editor;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Reader;
import java.util.concurrent.atomic.AtomicReference;
import javax.swing.ImageIcon;
import javax.swing.text.BadLocationException;
import javax.swing.text.StyledDocument;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.openide.cookies.EditorCookie;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.util.Exceptions;
import org.openide.util.ImageUtilities;
/**
*
* @author Petr pisl
*/
public class NodeJsUtils {
public static final String REQUIRE_METHOD_NAME = "require"; // NOI18N
public static final String ON_METHOD_NAME = "on"; // NOI18N
public static final String NODE_MODULES_NAME = "node_modules"; // NOI18N
public static final String PACKAGE_NAME = "package"; //NOI18N
public static final String INDEX_NAME = "index"; //NOI18N
public static final String FAKE_OBJECT_NAME_PREFIX = "nm$_"; //NOI18N
public static final String NODEJS_NAME = "NodeJS"; //NOI18N
public static final String JS_EXT = "js"; //NOI18N
public static final String JSON_EXT = "json"; //NOI18N
public static final String NODE_EXT = "node"; //NOI18N
private static final String MAIN_FIELD = "main"; //NOI18N
private static final String SLASH = "/"; //NOI18N
public static final String EXPORTS = "exports"; //NOI18N
public static final String MODULE = "module"; //NOI18N
public static final String PROTOTYPE = "prototype"; //NOI18N
private static final String NODEJS_ICON_PATH = "org/netbeans/modules/javascript2/nodejs/resources/nodeJs16.png"; //NOI18N
private static ImageIcon NODEJS_ICON = null;
public static ImageIcon getNodeJsIcon () {
if (NODEJS_ICON == null) {
NODEJS_ICON = new ImageIcon(ImageUtilities.loadImage(NODEJS_ICON_PATH)); //NOI18N
}
return NODEJS_ICON;
}
public static FileObject findModuleFile(FileObject fromModule, String modulePath) {
if (modulePath == null || modulePath.isEmpty()) {
// do nothing in such case
return null;
}
char firstChar = modulePath.charAt(0);
FileObject resultFO = null;
// we should now recognize, whether the identifier is a core module
// if (coreModule) return null;
if (firstChar == '/') {
File file = new File(modulePath);
if (file.exists()) {
resultFO = FileUtil.toFileObject(file);
}
if (resultFO != null && !resultFO.isFolder()) {
return resultFO;
}
return null;
}
if (firstChar == '.') {
resultFO = findModuleAsFile(fromModule, modulePath);
if (resultFO == null) {
resultFO = findModuleAsFolder(fromModule, modulePath);
}
if (resultFO != null) {
// we don't want to show .node files (binary files)
return NODE_EXT.equals(resultFO.getExt()) ? null : resultFO;
}
}
resultFO = findNodeModule(fromModule, modulePath);
if (resultFO != null) {
// we don't want to show .node files (binary files)
return NODE_EXT.equals(resultFO.getExt()) ? null : resultFO;
}
return null;
}
private static FileObject findModuleAsFile(final FileObject fromModule, final String module) {
FileObject parentFO = fromModule.isFolder() ? fromModule : fromModule.getParent();
if (parentFO != null) {
FileObject resultFO = parentFO.getFileObject(module);
if (resultFO != null && !resultFO.isFolder()) {
return resultFO;
}
resultFO = parentFO.getFileObject(module + '.' + JS_EXT);
if (resultFO != null && !resultFO.isFolder()) {
return resultFO;
}
resultFO = parentFO.getFileObject(module + '.' + JSON_EXT);
if (resultFO != null && !resultFO.isFolder()) {
return resultFO;
}
resultFO = parentFO.getFileObject(module + '.' + NODE_EXT);
if (resultFO != null && !resultFO.isFolder()) {
return resultFO;
}
}
return null;
}
private static FileObject findModuleAsFolder(final FileObject fromModule, final String module) {
FileObject parentFO = fromModule.isFolder() ? fromModule : fromModule.getParent();
if (parentFO == null) {
return null;
}
FileObject moduleFolderFO = parentFO.getFileObject(module);
if (moduleFolderFO != null && moduleFolderFO.isFolder()) {
FileObject packageFO = moduleFolderFO.getFileObject(PACKAGE_NAME + '.' + JSON_EXT);
FileObject resultFO = null;
if (packageFO != null && !packageFO.isFolder()) {
// need to parser package.json
// find "main" field
String valueOfMain = getValueOfMain(packageFO);
if (valueOfMain != null) {
resultFO = findModuleAsFile (packageFO, valueOfMain);
if (resultFO != null) {
return resultFO;
}
}
}
resultFO = parentFO.getFileObject(module + "/" + INDEX_NAME + '.' + JS_EXT);
if (resultFO != null && !resultFO.isFolder()) {
return resultFO;
}
resultFO = parentFO.getFileObject(module + "/" + INDEX_NAME + '.' + NODE_EXT);
if (resultFO != null && !resultFO.isFolder()) {
return resultFO;
}
}
return null;
}
private static FileObject findNodeModule(final FileObject fromModule, final String module) {
FileObject runtimeModule = getRuntimeModuleFile(fromModule, module);
if (runtimeModule != null) {
// the runtime modules has the biggest priority
return runtimeModule;
}
FileObject parentFolder = fromModule.isFolder() ? fromModule : fromModule.getParent();
// we have to go through parent/node_modules/modulePath
while (parentFolder != null) {
FileObject nodeModulesFO = parentFolder.getFileObject(NODE_MODULES_NAME);
if (nodeModulesFO != null) {
FileObject resultFO = findModuleAsFile(nodeModulesFO, module); //NOI18N
if (resultFO == null) {
resultFO = findModuleAsFolder(nodeModulesFO, module); //NOI18N
}
if (resultFO != null) {
return resultFO;
}
}
parentFolder = parentFolder.getParent();
}
return null;
}
private static FileObject getRuntimeModuleFile(final FileObject fromModule, final String module) {
FileObject runtime = NodeJsDataProvider.getDefault(fromModule).getFolderWithRuntimeSources();
FileObject result = null;
if (runtime != null && runtime.isFolder()) {
result = runtime.getFileObject(module, "js"); //NOI18N
}
return result;
}
private static String getValueOfMain(final FileObject file) {
String content = loadFileContent(file);
String value = null;
if (content != null && !content.isEmpty()) {
JSONObject root = (JSONObject) JSONValue.parse(content);
if (root != null) {
Object main = root.get(MAIN_FIELD);
if (main != null && main instanceof String) {
value = (String)main;
}
}
}
return value;
}
public static String loadFileContent(final FileObject file) {
Reader r = null;
try {
DataObject dobj = DataObject.find(file);
EditorCookie ec = dobj.getLookup().lookup(EditorCookie.class);
if (ec == null) {
return null;
}
final StyledDocument document = ec.openDocument();
final AtomicReference<String> docContentRef = new AtomicReference<>();
final AtomicReference<BadLocationException> bleRef = new AtomicReference<>();
document.render(new Runnable() {
@Override
public void run() {
try {
docContentRef.set(document.getText(0, document.getLength()));
} catch (BadLocationException ex) {
bleRef.set(ex);
}
}
});
if (bleRef.get() != null) {
return null;
}
return docContentRef.get();
} catch (FileNotFoundException ex) {
Exceptions.printStackTrace(ex);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
return ""; //NOI18N
}
public static String getModuleName(String modulePath) {
String name = modulePath;
if(name.indexOf('/') > -1) {
name = name.substring(name.lastIndexOf('/') + 1);
}
if(name.indexOf('.') > -1) {
name = name.substring(0, name.lastIndexOf('.'));
}
return name;
}
public static String writeFilePathForDocWindow(final FileObject fo) {
String path = fo.getPath();
String[] parts = path.split(SLASH);
StringBuilder sb = new StringBuilder();
sb.append("<pre>"); // NOI18N
int length = 0;
for (String part : parts) {
if ((length + part.length()) > 50) {
sb.append("\n "); // NOI18N
length = 4;
}
sb.append(part).append('/');
length += part.length() + 1;
}
sb.deleteCharAt(sb.length() - 1);
sb.append("</pre>"); // NOI18N
return sb.toString();
}
}