Added Contributions for libraries

This commit is contained in:
Cristian Maglie 2014-10-17 00:05:36 +02:00 committed by Federico Fissore
parent 75d1cb874d
commit 0b9223c158
12 changed files with 708 additions and 200 deletions

View File

@ -22,6 +22,15 @@
package processing.app; package processing.app;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import cc.arduino.libraries.contributions.LibrariesIndexer;
import cc.arduino.packages.DiscoveryManager; import cc.arduino.packages.DiscoveryManager;
import cc.arduino.packages.contributions.ui.ContributionManagerUI; import cc.arduino.packages.contributions.ui.ContributionManagerUI;
import cc.arduino.view.SplashScreenHelper; import cc.arduino.view.SplashScreenHelper;
@ -34,8 +43,9 @@ import processing.app.helpers.filefilters.OnlyFilesWithExtension;
import processing.app.javax.swing.filechooser.FileNameExtensionFilter; import processing.app.javax.swing.filechooser.FileNameExtensionFilter;
import processing.app.legacy.PApplet; import processing.app.legacy.PApplet;
import processing.app.macosx.ThinkDifferent; import processing.app.macosx.ThinkDifferent;
import processing.app.packages.Library; import processing.app.legacy.PConstants;
import processing.app.packages.LibraryList; import processing.app.packages.LibraryList;
import processing.app.packages.UserLibrary;
import processing.app.tools.MenuScroller; import processing.app.tools.MenuScroller;
import processing.app.tools.ZipDeflater; import processing.app.tools.ZipDeflater;
@ -1083,14 +1093,14 @@ public class Base {
// Add examples from libraries // Add examples from libraries
LibraryList ideLibs = getIDELibs(); LibraryList ideLibs = getIDELibs();
ideLibs.sort(); ideLibs.sort();
for (Library lib : ideLibs) for (UserLibrary lib : ideLibs)
addSketchesSubmenu(menu, lib, false); addSketchesSubmenu(menu, lib, false);
LibraryList userLibs = getUserLibs(); LibraryList userLibs = getUserLibs();
if (userLibs.size()>0) { if (userLibs.size()>0) {
menu.addSeparator(); menu.addSeparator();
userLibs.sort(); userLibs.sort();
for (Library lib : userLibs) for (UserLibrary lib : userLibs)
addSketchesSubmenu(menu, lib, false); addSketchesSubmenu(menu, lib, false);
} }
} catch (IOException e) { } catch (IOException e) {
@ -1098,14 +1108,6 @@ public class Base {
} }
} }
public LibraryList scanLibraries(List<File> folders) throws IOException {
return BaseNoGui.scanLibraries(folders);
}
public LibraryList scanLibraries(File folder) throws IOException {
return BaseNoGui.scanLibraries(folder);
}
public void onBoardOrPortChange() { public void onBoardOrPortChange() {
BaseNoGui.onBoardOrPortChange(); BaseNoGui.onBoardOrPortChange();
@ -1431,10 +1433,10 @@ public class Base {
return ifound; return ifound;
} }
private boolean addSketchesSubmenu(JMenu menu, Library lib, private boolean addSketchesSubmenu(JMenu menu, UserLibrary lib,
boolean replaceExisting) boolean replaceExisting)
throws IOException { throws IOException {
return addSketchesSubmenu(menu, lib.getName(), lib.getFolder(), return addSketchesSubmenu(menu, lib.getName(), lib.getInstalledFolder(),
replaceExisting); replaceExisting);
} }
@ -1516,11 +1518,11 @@ public class Base {
LibraryList list = new LibraryList(libs); LibraryList list = new LibraryList(libs);
list.sort(); list.sort();
for (Library lib : list) { for (UserLibrary lib : list) {
@SuppressWarnings("serial") @SuppressWarnings("serial")
AbstractAction action = new AbstractAction(lib.getName()) { AbstractAction action = new AbstractAction(lib.getName()) {
public void actionPerformed(ActionEvent event) { public void actionPerformed(ActionEvent event) {
Library l = (Library) getValue("library"); UserLibrary l = (UserLibrary) getValue("library");
try { try {
activeEditor.getSketch().importLibrary(l); activeEditor.getSketch().importLibrary(l);
} catch (IOException e) { } catch (IOException e) {

View File

@ -34,7 +34,8 @@ import processing.app.forms.PasswordAuthorizationDialog;
import processing.app.helpers.OSUtils; import processing.app.helpers.OSUtils;
import processing.app.helpers.PreferencesMap; import processing.app.helpers.PreferencesMap;
import processing.app.helpers.PreferencesMapException; import processing.app.helpers.PreferencesMapException;
import processing.app.packages.Library; import processing.app.packages.UserLibrary;
import static processing.app.I18n._;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
@ -938,7 +939,7 @@ public class Sketch {
} }
public void importLibrary(Library lib) throws IOException { public void importLibrary(UserLibrary lib) throws IOException {
importLibrary(lib.getSrcFolder()); importLibrary(lib.getSrcFolder());
} }

View File

@ -26,11 +26,12 @@ package processing.app.syntax;
import processing.app.*; import processing.app.*;
import processing.app.legacy.PApplet; import processing.app.legacy.PApplet;
import processing.app.packages.Library;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
import cc.arduino.libraries.contributions.ContributedLibrary;
public class PdeKeywords extends CTokenMarker { public class PdeKeywords extends CTokenMarker {
@ -61,8 +62,8 @@ public class PdeKeywords extends CTokenMarker {
keywordColoring = new KeywordMap(false); keywordColoring = new KeywordMap(false);
keywordToReference = new Hashtable(); keywordToReference = new Hashtable();
getKeywords(Base.getLibStream("keywords.txt")); getKeywords(Base.getLibStream("keywords.txt"));
for (Library lib : Base.getLibraries()) { for (ContributedLibrary lib : Base.getLibraries()) {
File keywords = new File(lib.getFolder(), "keywords.txt"); File keywords = new File(lib.getInstalledFolder(), "keywords.txt");
if (keywords.exists()) getKeywords(new FileInputStream(keywords)); if (keywords.exists()) getKeywords(new FileInputStream(keywords));
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -0,0 +1,140 @@
/*
* This file is part of Arduino.
*
* Copyright 2014 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package cc.arduino.libraries.contributions;
import java.util.Comparator;
import java.util.List;
import cc.arduino.packages.contributions.DownloadableContribution;
public abstract class ContributedLibrary extends DownloadableContribution {
public abstract String getName();
public abstract String getVersion();
public abstract String getMaintainer();
public abstract String getAuthor();
public abstract String getWebsite();
public abstract String getCategory();
public abstract String getLicense();
public abstract String getParagraph();
public abstract String getSentence();
public abstract String getSupportLevel();
public abstract List<String> getArchitectures();
public abstract List<ContributedLibraryReference> getRequires();
private boolean readOnly;
public boolean isReadOnly() {
return readOnly;
}
public void setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
}
public static final Comparator<ContributedLibrary> CASE_INSENSITIVE_ORDER = new Comparator<ContributedLibrary>() {
@Override
public int compare(ContributedLibrary o1, ContributedLibrary o2) {
return o1.getName().compareToIgnoreCase(o2.getName());
}
};
/**
* Returns <b>true</b> if the library declares to support the specified
* architecture (through the "architectures" property field).
*
* @param reqArch
* @return
*/
public boolean supportsArchitecture(String reqArch) {
return getArchitectures().contains(reqArch) ||
getArchitectures().contains("*");
}
/**
* Returns <b>true</b> if the library declares to support at least one of the
* specified architectures.
*
* @param reqArchs
* A List of architectures to check
* @return
*/
public boolean supportsArchitecture(List<String> reqArchs) {
if (reqArchs.contains("*"))
return true;
for (String reqArch : reqArchs)
if (supportsArchitecture(reqArch))
return true;
return false;
}
@Override
public String toString() {
String res = "";
res += " ContributedLibrary : " + getName() + "\n";
res += " author : " + getAuthor() + "\n";
res += " maintainer : " + getMaintainer() + "\n";
res += " version : " + getVersion() + "\n";
res += " website : " + getUrl() + "\n";
res += " category : " + getCategory() + "\n";
res += " license : " + getLicense() + "\n";
res += " descrip : " + getSentence() + "\n";
if (getParagraph() != null && !getParagraph().isEmpty())
res += " " + getParagraph() + "\n";
res += " architectures : ";
if (getArchitectures() != null)
for (String a : getArchitectures()) {
res += a + ",";
}
res += "\n";
res += " requires :\n";
if (getRequires() != null)
for (ContributedLibraryReference r : getRequires()) {
res += " " + r;
}
res += "\n";
// DownloadableContribution
res += super.toString();
return res;
}
}

View File

@ -0,0 +1,43 @@
/*
* This file is part of Arduino.
*
* Copyright 2014 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package cc.arduino.libraries.contributions;
public abstract class ContributedLibraryReference {
public abstract String getName();
public abstract String getMaintainer();
public abstract String getVersion();
@Override
public String toString() {
return getName() + " " + getVersion() + " (" + getMaintainer() + ")";
}
}

View File

@ -0,0 +1,52 @@
/*
* This file is part of Arduino.
*
* Copyright 2014 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package cc.arduino.libraries.contributions;
import java.util.List;
public abstract class LibrariesIndex {
public abstract List<ContributedLibrary> getLibraries();
public ContributedLibrary find(String name, String version) {
for (ContributedLibrary lib : getLibraries()) {
if (lib.getName().equals(name) && lib.getVersion().equals(version))
return lib;
}
return null;
}
@Override
public String toString() {
String res = "";
for (ContributedLibrary l : getLibraries())
res += l.toString();
return res;
}
}

View File

@ -0,0 +1,149 @@
/*
* This file is part of Arduino.
*
* Copyright 2014 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package cc.arduino.libraries.contributions;
import static processing.app.I18n._;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import processing.app.BaseNoGui;
import processing.app.I18n;
import processing.app.helpers.filefilters.OnlyDirs;
import processing.app.packages.LegacyUserLibrary;
import processing.app.packages.LibraryList;
import processing.app.packages.UserLibrary;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.mrbean.MrBeanModule;
public class LibrariesIndexer {
private LibrariesIndex index;
private File indexFile;
public LibrariesIndexer(File _settingsFolder) {
indexFile = new File(_settingsFolder, "library_index.json");
}
public void parseIndex() throws JsonParseException, IOException {
parseIndex(indexFile);
System.out.println(index);
// TODO: resolve libraries inner references
}
private void parseIndex(File indexFile) throws JsonParseException,
IOException {
InputStream indexIn = new FileInputStream(indexFile);
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new MrBeanModule());
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
mapper.configure(DeserializationFeature.EAGER_DESERIALIZER_FETCH, true);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
index = mapper.readValue(indexIn, LibrariesIndex.class);
}
public LibraryList scanLibraries(List<File> folders) throws IOException {
LibraryList res = new LibraryList();
for (File folder : folders)
res.addOrReplaceAll(scanLibraries(folder));
return res;
}
private LibraryList scanLibraries(File folder) throws IOException {
LibraryList res = new LibraryList();
File list[] = folder.listFiles(new OnlyDirs());
// if a bad folder or something like that, this might come back null
if (list == null)
return res;
for (File subfolder : list) {
if (!BaseNoGui.isSanitaryName(subfolder.getName())) {
String mess = I18n
.format(_("The library \"{0}\" cannot be used.\n"
+ "Library names must contain only basic letters and numbers.\n"
+ "(ASCII only and no spaces, and it cannot start with a number)"),
subfolder.getName());
BaseNoGui.showMessage(_("Ignoring bad library name"), mess);
continue;
}
try {
ContributedLibrary lib = scanLibrary(subfolder);
// (also replace previously found libs with the same name)
if (lib != null)
res.addOrReplace(lib);
} catch (IOException e) {
System.out.println(I18n.format(_("Invalid library found in {0}: {1}"),
subfolder, e.getMessage()));
}
}
return res;
}
private ContributedLibrary scanLibrary(File subfolder) throws IOException {
// A library is considered non-Legacy if it contains
// a file called "library.properties"
File check = new File(subfolder, "library.properties");
if (!check.exists() || !check.isFile())
return LegacyUserLibrary.create(subfolder);
ContributedLibrary lib = UserLibrary.create(subfolder);
// Check if we can find the same library in the index
// String libName = subfolder.getName(); // XXX: lib.getName()?
// ContributedLibrary foundLib = index.find(libName, lib.getVersion());
// if (foundLib != null) {
// foundLib.setInstalled(true);
// foundLib.setInstalledFolder(subfolder);
// return foundLib;
// }
return lib;
}
public static void main(String[] args) throws JsonParseException, IOException {
LibrariesIndexer indexer = new LibrariesIndexer(new File(
"/home/megabug/.arduino15"));
indexer.parseIndex();
LibraryList libs = indexer.scanLibraries(new File(
"/home/megabug/sketchbook/libraries"));
for (ContributedLibrary lib : libs) {
System.out.println(lib);
}
}
}

View File

@ -19,6 +19,8 @@ import org.apache.commons.logging.impl.NoOpLog;
import cc.arduino.packages.DiscoveryManager; import cc.arduino.packages.DiscoveryManager;
import cc.arduino.packages.Uploader; import cc.arduino.packages.Uploader;
import processing.app.debug.Compiler; import processing.app.debug.Compiler;
import cc.arduino.libraries.contributions.LibrariesIndexer;
import cc.arduino.packages.contributions.ContributionsIndexer; import cc.arduino.packages.contributions.ContributionsIndexer;
import cc.arduino.utils.ArchiveExtractor; import cc.arduino.utils.ArchiveExtractor;
import processing.app.debug.TargetBoard; import processing.app.debug.TargetBoard;
@ -34,8 +36,8 @@ import processing.app.helpers.UserNotifier;
import processing.app.helpers.filefilters.OnlyDirs; import processing.app.helpers.filefilters.OnlyDirs;
import processing.app.helpers.filefilters.OnlyFilesWithExtension; import processing.app.helpers.filefilters.OnlyFilesWithExtension;
import processing.app.legacy.PApplet; import processing.app.legacy.PApplet;
import processing.app.packages.Library;
import processing.app.packages.LibraryList; import processing.app.packages.LibraryList;
import processing.app.packages.UserLibrary;
public class BaseNoGui { public class BaseNoGui {
@ -57,7 +59,7 @@ public class BaseNoGui {
static private File toolsFolder; static private File toolsFolder;
// maps #included files to their library folder // maps #included files to their library folder
public static Map<String, Library> importToLibraryTable; public static Map<String, UserLibrary> importToLibraryTable;
// maps library name to their library folder // maps library name to their library folder
static private LibraryList libraries; static private LibraryList libraries;
@ -74,6 +76,7 @@ public class BaseNoGui {
static final String portableSketchbookFolder = "sketchbook"; static final String portableSketchbookFolder = "sketchbook";
static ContributionsIndexer indexer; static ContributionsIndexer indexer;
static LibrariesIndexer librariesIndexer;
// Returns a File object for the given pathname. If the pathname // Returns a File object for the given pathname. If the pathname
// is not absolute, it is interpreted relative to the current // is not absolute, it is interpreted relative to the current
@ -615,6 +618,9 @@ public class BaseNoGui {
loadHardware(getHardwareFolder()); loadHardware(getHardwareFolder());
loadHardware(getSketchbookHardwareFolder()); loadHardware(getSketchbookHardwareFolder());
loadContributedHardware(indexer); loadContributedHardware(indexer);
librariesIndexer = new LibrariesIndexer(BaseNoGui.getSettingsFolder());
librariesIndexer.parseIndex();
} }
static protected void initPlatform() { static protected void initPlatform() {
@ -708,9 +714,10 @@ public class BaseNoGui {
examplesFolder = getContentFile("examples"); examplesFolder = getContentFile("examples");
toolsFolder = getContentFile("tools"); toolsFolder = getContentFile("tools");
librariesFolders = new ArrayList<File>(); librariesFolders = new ArrayList<File>();
// Add IDE libraries folder
librariesFolders.add(getContentFile("libraries")); librariesFolders.add(getContentFile("libraries"));
// Add library folder for the current selected platform
TargetPlatform targetPlatform = getTargetPlatform(); TargetPlatform targetPlatform = getTargetPlatform();
if (targetPlatform != null) { if (targetPlatform != null) {
String core = getBoardPreferences().get("build.core", "arduino"); String core = getBoardPreferences().get("build.core", "arduino");
@ -719,14 +726,18 @@ public class BaseNoGui {
TargetPlatform referencedPlatform = getTargetPlatform(referencedCore, targetPlatform.getId()); TargetPlatform referencedPlatform = getTargetPlatform(referencedCore, targetPlatform.getId());
if (referencedPlatform != null) { if (referencedPlatform != null) {
File referencedPlatformFolder = referencedPlatform.getFolder(); File referencedPlatformFolder = referencedPlatform.getFolder();
// Add libraries folder for the referenced platform
librariesFolders.add(new File(referencedPlatformFolder, "libraries")); librariesFolders.add(new File(referencedPlatformFolder, "libraries"));
} }
} }
File platformFolder = targetPlatform.getFolder(); File platformFolder = targetPlatform.getFolder();
// Add libraries folder for the selected platform
librariesFolders.add(new File(platformFolder, "libraries")); librariesFolders.add(new File(platformFolder, "libraries"));
librariesFolders.add(getSketchbookLibrariesFolder());
} }
// Add libraries folder for the sketchbook
librariesFolders.add(getSketchbookLibrariesFolder());
// Scan for libraries in each library folder. // Scan for libraries in each library folder.
// Libraries located in the latest folders on the list can override // Libraries located in the latest folders on the list can override
// other libraries with the same name. // other libraries with the same name.
@ -747,12 +758,12 @@ public class BaseNoGui {
static public void populateImportToLibraryTable() { static public void populateImportToLibraryTable() {
// Populate importToLibraryTable // Populate importToLibraryTable
importToLibraryTable = new HashMap<String, Library>(); importToLibraryTable = new HashMap<String, UserLibrary>();
for (Library lib : getLibraries()) { for (UserLibrary lib : getLibraries()) {
try { try {
String headers[] = headerListFromIncludePath(lib.getSrcFolder()); String headers[] = headerListFromIncludePath(lib.getSrcFolder());
for (String header : headers) { for (String header : headers) {
Library old = importToLibraryTable.get(header); UserLibrary old = importToLibraryTable.get(header);
if (old != null) { if (old != null) {
// This is the case where 2 libraries have a .h header // This is the case where 2 libraries have a .h header
// with the same name. We must decide which library to // with the same name. We must decide which library to
@ -768,8 +779,8 @@ public class BaseNoGui {
// for "libName", then for "oldName". // for "libName", then for "oldName".
// //
String name = header.substring(0, header.length() - 2); // name without ".h" String name = header.substring(0, header.length() - 2); // name without ".h"
String oldName = old.getFolder().getName(); // just the library folder name String oldName = old.getInstalledFolder().getName(); // just the library folder name
String libName = lib.getFolder().getName(); // just the library folder name String libName = lib.getInstalledFolder().getName(); // just the library folder name
//System.out.println("name conflict: " + name); //System.out.println("name conflict: " + name);
//System.out.println(" old = " + oldName + " -> " + old.getFolder().getPath()); //System.out.println(" old = " + oldName + " -> " + old.getFolder().getPath());
//System.out.println(" new = " + libName + " -> " + lib.getFolder().getPath()); //System.out.println(" new = " + libName + " -> " + lib.getFolder().getPath());
@ -962,42 +973,7 @@ public class BaseNoGui {
} }
static public LibraryList scanLibraries(List<File> folders) throws IOException { static public LibraryList scanLibraries(List<File> folders) throws IOException {
LibraryList res = new LibraryList(); return librariesIndexer.scanLibraries(folders);
for (File folder : folders)
res.addOrReplaceAll(scanLibraries(folder));
return res;
}
static public LibraryList scanLibraries(File folder) throws IOException {
LibraryList res = new LibraryList();
String list[] = folder.list(new OnlyDirs());
// if a bad folder or something like that, this might come back null
if (list == null)
return res;
for (String libName : list) {
File subfolder = new File(folder, libName);
if (!isSanitaryName(libName)) {
String mess = I18n.format(_("The library \"{0}\" cannot be used.\n"
+ "Library names must contain only basic letters and numbers.\n"
+ "(ASCII only and no spaces, and it cannot start with a number)"),
libName);
showMessage(_("Ignoring bad library name"), mess);
continue;
}
try {
Library lib = Library.create(subfolder);
// (also replace previously found libs with the same name)
if (lib != null)
res.addOrReplace(lib);
} catch (IOException e) {
System.out.println(I18n.format(_("Invalid library found in {0}: {1}"),
subfolder, e.getMessage()));
}
}
return res;
} }
static public void selectBoard(TargetBoard targetBoard) { static public void selectBoard(TargetBoard targetBoard) {

View File

@ -52,10 +52,11 @@ import processing.app.SketchCode;
import processing.app.SketchData; import processing.app.SketchData;
import processing.app.helpers.*; import processing.app.helpers.*;
import processing.app.helpers.filefilters.OnlyDirs; import processing.app.helpers.filefilters.OnlyDirs;
import processing.app.packages.Library;
import processing.app.packages.LibraryList; import processing.app.packages.LibraryList;
import processing.app.preproc.PdePreprocessor; import processing.app.preproc.PdePreprocessor;
import processing.app.legacy.PApplet; import processing.app.legacy.PApplet;
import processing.app.packages.LegacyUserLibrary;
import processing.app.packages.UserLibrary;
public class Compiler implements MessageConsumer { public class Compiler implements MessageConsumer {
@ -361,11 +362,15 @@ public class Compiler implements MessageConsumer {
includeFolders.add(prefs.getFile("build.core.path")); includeFolders.add(prefs.getFile("build.core.path"));
if (prefs.getFile("build.variant.path") != null) if (prefs.getFile("build.variant.path") != null)
includeFolders.add(prefs.getFile("build.variant.path")); includeFolders.add(prefs.getFile("build.variant.path"));
for (Library lib : importedLibraries) { for (UserLibrary lib : importedLibraries) {
if (verbose) if (verbose) {
String legacy = "";
if (lib instanceof LegacyUserLibrary)
legacy = "(legacy)";
System.out.println(I18n System.out.println(I18n
.format(_("Using library {0} in folder: {1} {2}"), lib.getName(), .format(_("Using library {0} in folder: {1} {2}"), lib.getName(),
lib.getFolder(), lib.isLegacy() ? "(legacy)" : "")); lib.getInstalledFolder(), legacy));
}
includeFolders.add(lib.getSrcFolder()); includeFolders.add(lib.getSrcFolder());
} }
if (verbose) if (verbose)
@ -377,7 +382,7 @@ public class Compiler implements MessageConsumer {
String[] overrides = prefs.get("architecture.override_check").split(","); String[] overrides = prefs.get("architecture.override_check").split(",");
archs.addAll(Arrays.asList(overrides)); archs.addAll(Arrays.asList(overrides));
} }
for (Library lib : importedLibraries) { for (UserLibrary lib : importedLibraries) {
if (!lib.supportsArchitecture(archs)) { if (!lib.supportsArchitecture(archs)) {
System.err.println(I18n System.err.println(I18n
.format(_("WARNING: library {0} claims to run on {1} " .format(_("WARNING: library {0} claims to run on {1} "
@ -890,12 +895,12 @@ public class Compiler implements MessageConsumer {
// 2. compile the libraries, outputting .o files to: // 2. compile the libraries, outputting .o files to:
// <buildPath>/<library>/ // <buildPath>/<library>/
void compileLibraries(List<File> includeFolders) throws RunnerException, PreferencesMapException { void compileLibraries(List<File> includeFolders) throws RunnerException, PreferencesMapException {
for (Library lib : importedLibraries) { for (UserLibrary lib : importedLibraries) {
compileLibrary(lib, includeFolders); compileLibrary(lib, includeFolders);
} }
} }
private void compileLibrary(Library lib, List<File> includeFolders) private void compileLibrary(UserLibrary lib, List<File> includeFolders)
throws RunnerException, PreferencesMapException { throws RunnerException, PreferencesMapException {
File libFolder = lib.getSrcFolder(); File libFolder = lib.getSrcFolder();
File libBuildFolder = prefs.getFile(("build.path"), lib.getName()); File libBuildFolder = prefs.getFile(("build.path"), lib.getName());
@ -1162,7 +1167,7 @@ public class Compiler implements MessageConsumer {
importedLibraries = new LibraryList(); importedLibraries = new LibraryList();
for (String item : preprocessor.getExtraImports()) { for (String item : preprocessor.getExtraImports()) {
Library lib = BaseNoGui.importToLibraryTable.get(item); UserLibrary lib = BaseNoGui.importToLibraryTable.get(item);
if (lib != null && !importedLibraries.contains(lib)) { if (lib != null && !importedLibraries.contains(lib)) {
importedLibraries.add(lib); importedLibraries.add(lib);
} }

View File

@ -0,0 +1,132 @@
/*
* This file is part of Arduino.
*
* Copyright 2014 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package processing.app.packages;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import cc.arduino.libraries.contributions.ContributedLibraryReference;
public class LegacyUserLibrary extends UserLibrary {
private String name;
public static LegacyUserLibrary create(File libFolder) {
// construct an old style library
LegacyUserLibrary res = new LegacyUserLibrary();
res.setInstalledFolder(libFolder);
res.setInstalled(true);
res.layout = LibraryLayout.FLAT;
res.name = libFolder.getName();
return res;
}
@Override
public String getName() {
return name;
}
@Override
public List<String> getArchitectures() {
return Arrays.asList("*");
}
@Override
public String getAuthor() {
return null;
}
@Override
public String getParagraph() {
return null;
}
@Override
public String getSentence() {
return null;
}
@Override
public String getWebsite() {
return null;
}
@Override
public String getCategory() {
return null;
}
@Override
public String getLicense() {
return null;
}
@Override
public String getVersion() {
return null;
}
@Override
public String getMaintainer() {
return null;
}
@Override
public String getChecksum() {
return null;
}
@Override
public long getSize() {
return 0;
}
@Override
public String getUrl() {
return null;
}
@Override
public List<ContributedLibraryReference> getRequires() {
return null;
}
@Override
public String toString() {
String res = "LegacyLibrary:";
res += " (name=" + name + ")";
return res;
}
@Override
public String getSupportLevel() {
return "Unsupported";
}
}

View File

@ -1,3 +1,31 @@
/*
* This file is part of Arduino.
*
* Copyright 2014 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package processing.app.packages; package processing.app.packages;
import java.io.File; import java.io.File;
@ -8,7 +36,7 @@ import java.util.Collections;
import processing.app.helpers.FileUtils; import processing.app.helpers.FileUtils;
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class LibraryList extends ArrayList<Library> { public class LibraryList extends ArrayList<UserLibrary> {
public LibraryList(LibraryList libs) { public LibraryList(LibraryList libs) {
super(libs); super(libs);
@ -18,52 +46,33 @@ public class LibraryList extends ArrayList<Library> {
super(); super();
} }
public Library getByName(String name) { public UserLibrary getByName(String name) {
for (Library l : this) for (UserLibrary l : this)
if (l.getName().equals(name)) if (l.getName().equals(name))
return l; return l;
return null; return null;
} }
public void addOrReplace(Library lib) { public void addOrReplace(UserLibrary lib) {
Library l = getByName(lib.getName()); UserLibrary l = getByName(lib.getName());
if (l != null) if (l != null)
remove(l); remove(l);
add(lib); add(lib);
} }
public void addOrReplaceAll(Collection<? extends Library> c) { public void addOrReplaceAll(Collection<? extends UserLibrary> c) {
for (Library l : c) for (UserLibrary l : c)
addOrReplace(l); addOrReplace(l);
} }
public void sort() { public void sort() {
Collections.sort(this, Library.CASE_INSENSITIVE_ORDER); Collections.sort(this, UserLibrary.CASE_INSENSITIVE_ORDER);
}
public Library search(String name, String arch) {
for (Library lib : this) {
if (!lib.getName().equals(name))
continue;
if (!lib.supportsArchitecture(arch))
continue;
return lib;
}
return null;
}
public LibraryList filterByArchitecture(String reqArch) {
LibraryList res = new LibraryList();
for (Library lib : this)
if (lib.supportsArchitecture(reqArch))
res.add(lib);
return res;
} }
public LibraryList filterLibrariesInSubfolder(File subFolder) { public LibraryList filterLibrariesInSubfolder(File subFolder) {
LibraryList res = new LibraryList(); LibraryList res = new LibraryList();
for (Library lib : this) for (UserLibrary lib : this)
if (FileUtils.isSubDirectory(subFolder, lib.getFolder())) if (FileUtils.isSubDirectory(subFolder, lib.getInstalledFolder()))
res.add(lib); res.add(lib);
return res; return res;
} }

View File

@ -1,16 +1,45 @@
/*
* This file is part of Arduino.
*
* Copyright 2014 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package processing.app.packages; package processing.app.packages;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator;
import java.util.List; import java.util.List;
import processing.app.helpers.FileUtils; import processing.app.helpers.FileUtils;
import processing.app.helpers.PreferencesMap; import processing.app.helpers.PreferencesMap;
import cc.arduino.libraries.contributions.ContributedLibrary;
import cc.arduino.libraries.contributions.ContributedLibraryReference;
public class Library { public class UserLibrary extends ContributedLibrary {
private String name; private String name;
private String version; private String version;
@ -18,15 +47,10 @@ public class Library {
private String maintainer; private String maintainer;
private String sentence; private String sentence;
private String paragraph; private String paragraph;
private String url; private String website;
private String category; private String category;
private String license; private String license;
private List<String> architectures; private List<String> architectures;
private File folder;
private boolean isLegacy;
private enum LibraryLayout { FLAT, RECURSIVE };
private LibraryLayout layout;
private static final List<String> MANDATORY_PROPERTIES = Arrays private static final List<String> MANDATORY_PROPERTIES = Arrays
.asList(new String[] { "name", "version", "author", "maintainer", .asList(new String[] { "name", "version", "author", "maintainer",
@ -37,25 +61,7 @@ public class Library {
"Device Control", "Timing", "Data Storage", "Data Processing", "Other", "Device Control", "Timing", "Data Storage", "Data Processing", "Other",
"Uncategorized" }); "Uncategorized" });
/** public static UserLibrary create(File libFolder) throws IOException {
* Scans inside a folder and create a Library object out of it. Automatically
* detects legacy libraries. Automatically fills metadata from
* library.properties file if found.
*
* @param libFolder
* @return
*/
static public Library create(File libFolder) throws IOException {
// A library is considered "new" if it contains a file called
// "library.properties"
File check = new File(libFolder, "library.properties");
if (!check.exists() || !check.isFile())
return createLegacyLibrary(libFolder);
else
return createLibrary(libFolder);
}
private static Library createLibrary(File libFolder) throws IOException {
// Parse metadata // Parse metadata
File propertiesFile = new File(libFolder, "library.properties"); File propertiesFile = new File(libFolder, "library.properties");
PreferencesMap properties = new PreferencesMap(); PreferencesMap properties = new PreferencesMap();
@ -132,101 +138,59 @@ public class Library {
if (license == null) if (license == null)
license = "Unspecified"; license = "Unspecified";
Library res = new Library(); UserLibrary res = new UserLibrary();
res.folder = libFolder; res.setInstalledFolder(libFolder);
res.setInstalled(true);
res.name = properties.get("name").trim(); res.name = properties.get("name").trim();
res.version = properties.get("version").trim(); res.version = properties.get("version").trim();
res.author = properties.get("author").trim(); res.author = properties.get("author").trim();
res.maintainer = properties.get("maintainer").trim(); res.maintainer = properties.get("maintainer").trim();
res.sentence = properties.get("sentence").trim(); res.sentence = properties.get("sentence").trim();
res.paragraph = properties.get("paragraph").trim(); res.paragraph = properties.get("paragraph").trim();
res.url = properties.get("url").trim(); res.website = properties.get("url").trim();
res.category = category.trim(); res.category = category.trim();
res.license = license.trim(); res.license = license.trim();
res.architectures = archs; res.architectures = archs;
res.isLegacy = false;
res.layout = layout; res.layout = layout;
return res; return res;
} }
private static Library createLegacyLibrary(File libFolder) { @Override
// construct an old style library
Library res = new Library();
res.folder = libFolder;
res.layout = LibraryLayout.FLAT;
res.name = libFolder.getName();
res.architectures = Arrays.asList("*");
res.isLegacy = true;
return res;
}
/**
* Returns <b>true</b> if the library declares to support the specified
* architecture (through the "architectures" property field).
*
* @param reqArch
* @return
*/
public boolean supportsArchitecture(String reqArch) {
return architectures.contains(reqArch) || architectures.contains("*");
}
/**
* Returns <b>true</b> if the library declares to support at least one of the
* specified architectures.
*
* @param reqArchs
* A List of architectures to check
* @return
*/
public boolean supportsArchitecture(List<String> reqArchs) {
if (reqArchs.contains("*"))
return true;
for (String reqArch : reqArchs)
if (supportsArchitecture(reqArch))
return true;
return false;
}
public static final Comparator<Library> CASE_INSENSITIVE_ORDER = new Comparator<Library>() {
@Override
public int compare(Library o1, Library o2) {
return o1.getName().compareToIgnoreCase(o2.getName());
}
};
public String getName() { public String getName() {
return name; return name;
} }
public File getFolder() { @Override
return folder;
}
public List<String> getArchitectures() { public List<String> getArchitectures() {
return architectures; return architectures;
} }
@Override
public String getAuthor() { public String getAuthor() {
return author; return author;
} }
@Override
public String getParagraph() { public String getParagraph() {
return paragraph; return paragraph;
} }
@Override
public String getSentence() { public String getSentence() {
return sentence; return sentence;
} }
public String getUrl() { @Override
return url; public String getWebsite() {
return website;
} }
@Override
public String getCategory() { public String getCategory() {
return category; return category;
} }
@Override
public String getLicense() { public String getLicense() {
return license; return license;
} }
@ -235,31 +199,60 @@ public class Library {
return CATEGORIES; return CATEGORIES;
} }
@Override
public String getVersion() { public String getVersion() {
return version; return version;
} }
@Override
public String getMaintainer() { public String getMaintainer() {
return maintainer; return maintainer;
} }
public boolean useRecursion() { @Override
return (layout == LibraryLayout.RECURSIVE); public String getChecksum() {
return null;
} }
@Override
public long getSize() {
return 0;
}
@Override
public String getUrl() {
return null;
}
@Override
public String getArchiveFileName() {
return null;
}
@Override
public List<ContributedLibraryReference> getRequires() {
return null;
}
protected enum LibraryLayout {
FLAT, RECURSIVE
};
protected LibraryLayout layout;
public File getSrcFolder() { public File getSrcFolder() {
switch (layout) { switch (layout) {
case FLAT: case FLAT:
return folder; return getInstalledFolder();
case RECURSIVE: case RECURSIVE:
return new File(folder, "src"); return new File(getInstalledFolder(), "src");
default: default:
return null; // Keep compiler happy :-( return null; // Keep compiler happy :-(
} }
} }
public boolean isLegacy() { public boolean useRecursion() {
return isLegacy; return (layout == LibraryLayout.RECURSIVE);
} }
@Override @Override
@ -271,8 +264,13 @@ public class Library {
res += " (maintainer=" + maintainer + ")"; res += " (maintainer=" + maintainer + ")";
res += " (sentence=" + sentence + ")"; res += " (sentence=" + sentence + ")";
res += " (paragraph=" + paragraph + ")"; res += " (paragraph=" + paragraph + ")";
res += " (url=" + url + ")"; res += " (url=" + website + ")";
res += " (architectures=" + architectures + ")"; res += " (architectures=" + architectures + ")";
return res; return res;
} }
@Override
public String getSupportLevel() {
return "Unsupported";
}
} }