diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 9041bc0c5..c7dfa074c 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -22,6 +22,15 @@ 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.contributions.ui.ContributionManagerUI; 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.legacy.PApplet; import processing.app.macosx.ThinkDifferent; -import processing.app.packages.Library; +import processing.app.legacy.PConstants; import processing.app.packages.LibraryList; +import processing.app.packages.UserLibrary; import processing.app.tools.MenuScroller; import processing.app.tools.ZipDeflater; @@ -1083,14 +1093,14 @@ public class Base { // Add examples from libraries LibraryList ideLibs = getIDELibs(); ideLibs.sort(); - for (Library lib : ideLibs) + for (UserLibrary lib : ideLibs) addSketchesSubmenu(menu, lib, false); LibraryList userLibs = getUserLibs(); if (userLibs.size()>0) { menu.addSeparator(); userLibs.sort(); - for (Library lib : userLibs) + for (UserLibrary lib : userLibs) addSketchesSubmenu(menu, lib, false); } } catch (IOException e) { @@ -1098,14 +1108,6 @@ public class Base { } } - public LibraryList scanLibraries(List folders) throws IOException { - return BaseNoGui.scanLibraries(folders); - } - - public LibraryList scanLibraries(File folder) throws IOException { - return BaseNoGui.scanLibraries(folder); - } - public void onBoardOrPortChange() { BaseNoGui.onBoardOrPortChange(); @@ -1431,10 +1433,10 @@ public class Base { return ifound; } - private boolean addSketchesSubmenu(JMenu menu, Library lib, + private boolean addSketchesSubmenu(JMenu menu, UserLibrary lib, boolean replaceExisting) throws IOException { - return addSketchesSubmenu(menu, lib.getName(), lib.getFolder(), + return addSketchesSubmenu(menu, lib.getName(), lib.getInstalledFolder(), replaceExisting); } @@ -1516,11 +1518,11 @@ public class Base { LibraryList list = new LibraryList(libs); list.sort(); - for (Library lib : list) { + for (UserLibrary lib : list) { @SuppressWarnings("serial") AbstractAction action = new AbstractAction(lib.getName()) { public void actionPerformed(ActionEvent event) { - Library l = (Library) getValue("library"); + UserLibrary l = (UserLibrary) getValue("library"); try { activeEditor.getSketch().importLibrary(l); } catch (IOException e) { diff --git a/app/src/processing/app/Sketch.java b/app/src/processing/app/Sketch.java index 2f142d01b..54a9f9a0d 100644 --- a/app/src/processing/app/Sketch.java +++ b/app/src/processing/app/Sketch.java @@ -34,7 +34,8 @@ import processing.app.forms.PasswordAuthorizationDialog; import processing.app.helpers.OSUtils; import processing.app.helpers.PreferencesMap; import processing.app.helpers.PreferencesMapException; -import processing.app.packages.Library; +import processing.app.packages.UserLibrary; +import static processing.app.I18n._; import javax.swing.*; 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()); } diff --git a/app/src/processing/app/syntax/PdeKeywords.java b/app/src/processing/app/syntax/PdeKeywords.java index ccf52531c..2a837fab9 100644 --- a/app/src/processing/app/syntax/PdeKeywords.java +++ b/app/src/processing/app/syntax/PdeKeywords.java @@ -26,11 +26,12 @@ package processing.app.syntax; import processing.app.*; import processing.app.legacy.PApplet; -import processing.app.packages.Library; import java.io.*; import java.util.*; +import cc.arduino.libraries.contributions.ContributedLibrary; + public class PdeKeywords extends CTokenMarker { @@ -61,8 +62,8 @@ public class PdeKeywords extends CTokenMarker { keywordColoring = new KeywordMap(false); keywordToReference = new Hashtable(); getKeywords(Base.getLibStream("keywords.txt")); - for (Library lib : Base.getLibraries()) { - File keywords = new File(lib.getFolder(), "keywords.txt"); + for (ContributedLibrary lib : Base.getLibraries()) { + File keywords = new File(lib.getInstalledFolder(), "keywords.txt"); if (keywords.exists()) getKeywords(new FileInputStream(keywords)); } } catch (Exception e) { diff --git a/arduino-core/src/cc/arduino/libraries/contributions/ContributedLibrary.java b/arduino-core/src/cc/arduino/libraries/contributions/ContributedLibrary.java new file mode 100644 index 000000000..255338bb1 --- /dev/null +++ b/arduino-core/src/cc/arduino/libraries/contributions/ContributedLibrary.java @@ -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 getArchitectures(); + + public abstract List getRequires(); + + private boolean readOnly; + + public boolean isReadOnly() { + return readOnly; + } + + public void setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + } + + public static final Comparator CASE_INSENSITIVE_ORDER = new Comparator() { + @Override + public int compare(ContributedLibrary o1, ContributedLibrary o2) { + return o1.getName().compareToIgnoreCase(o2.getName()); + } + }; + + /** + * Returns true 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 true 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 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; + } + +} diff --git a/arduino-core/src/cc/arduino/libraries/contributions/ContributedLibraryReference.java b/arduino-core/src/cc/arduino/libraries/contributions/ContributedLibraryReference.java new file mode 100644 index 000000000..bed24fb64 --- /dev/null +++ b/arduino-core/src/cc/arduino/libraries/contributions/ContributedLibraryReference.java @@ -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() + ")"; + } +} diff --git a/arduino-core/src/cc/arduino/libraries/contributions/LibrariesIndex.java b/arduino-core/src/cc/arduino/libraries/contributions/LibrariesIndex.java new file mode 100644 index 000000000..07cccd339 --- /dev/null +++ b/arduino-core/src/cc/arduino/libraries/contributions/LibrariesIndex.java @@ -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 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; + } +} diff --git a/arduino-core/src/cc/arduino/libraries/contributions/LibrariesIndexer.java b/arduino-core/src/cc/arduino/libraries/contributions/LibrariesIndexer.java new file mode 100644 index 000000000..a8697c6d8 --- /dev/null +++ b/arduino-core/src/cc/arduino/libraries/contributions/LibrariesIndexer.java @@ -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 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); + } + } +} diff --git a/arduino-core/src/processing/app/BaseNoGui.java b/arduino-core/src/processing/app/BaseNoGui.java index 06f892746..b08ae891f 100644 --- a/arduino-core/src/processing/app/BaseNoGui.java +++ b/arduino-core/src/processing/app/BaseNoGui.java @@ -19,6 +19,8 @@ import org.apache.commons.logging.impl.NoOpLog; import cc.arduino.packages.DiscoveryManager; import cc.arduino.packages.Uploader; import processing.app.debug.Compiler; + +import cc.arduino.libraries.contributions.LibrariesIndexer; import cc.arduino.packages.contributions.ContributionsIndexer; import cc.arduino.utils.ArchiveExtractor; 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.OnlyFilesWithExtension; import processing.app.legacy.PApplet; -import processing.app.packages.Library; import processing.app.packages.LibraryList; +import processing.app.packages.UserLibrary; public class BaseNoGui { @@ -57,7 +59,7 @@ public class BaseNoGui { static private File toolsFolder; // maps #included files to their library folder - public static Map importToLibraryTable; + public static Map importToLibraryTable; // maps library name to their library folder static private LibraryList libraries; @@ -74,6 +76,7 @@ public class BaseNoGui { static final String portableSketchbookFolder = "sketchbook"; static ContributionsIndexer indexer; + static LibrariesIndexer librariesIndexer; // Returns a File object for the given pathname. If the pathname // is not absolute, it is interpreted relative to the current @@ -615,6 +618,9 @@ public class BaseNoGui { loadHardware(getHardwareFolder()); loadHardware(getSketchbookHardwareFolder()); loadContributedHardware(indexer); + + librariesIndexer = new LibrariesIndexer(BaseNoGui.getSettingsFolder()); + librariesIndexer.parseIndex(); } static protected void initPlatform() { @@ -708,9 +714,10 @@ public class BaseNoGui { examplesFolder = getContentFile("examples"); toolsFolder = getContentFile("tools"); librariesFolders = new ArrayList(); + + // Add IDE libraries folder librariesFolders.add(getContentFile("libraries")); - // Add library folder for the current selected platform TargetPlatform targetPlatform = getTargetPlatform(); if (targetPlatform != null) { String core = getBoardPreferences().get("build.core", "arduino"); @@ -719,14 +726,18 @@ public class BaseNoGui { TargetPlatform referencedPlatform = getTargetPlatform(referencedCore, targetPlatform.getId()); if (referencedPlatform != null) { File referencedPlatformFolder = referencedPlatform.getFolder(); + // Add libraries folder for the referenced platform librariesFolders.add(new File(referencedPlatformFolder, "libraries")); } } File platformFolder = targetPlatform.getFolder(); + // Add libraries folder for the selected platform 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. // Libraries located in the latest folders on the list can override // other libraries with the same name. @@ -747,12 +758,12 @@ public class BaseNoGui { static public void populateImportToLibraryTable() { // Populate importToLibraryTable - importToLibraryTable = new HashMap(); - for (Library lib : getLibraries()) { + importToLibraryTable = new HashMap(); + for (UserLibrary lib : getLibraries()) { try { String headers[] = headerListFromIncludePath(lib.getSrcFolder()); for (String header : headers) { - Library old = importToLibraryTable.get(header); + UserLibrary old = importToLibraryTable.get(header); if (old != null) { // This is the case where 2 libraries have a .h header // with the same name. We must decide which library to @@ -768,8 +779,8 @@ public class BaseNoGui { // for "libName", then for "oldName". // String name = header.substring(0, header.length() - 2); // name without ".h" - String oldName = old.getFolder().getName(); // just the library folder name - String libName = lib.getFolder().getName(); // just the library folder name + String oldName = old.getInstalledFolder().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(" old = " + oldName + " -> " + old.getFolder().getPath()); //System.out.println(" new = " + libName + " -> " + lib.getFolder().getPath()); @@ -962,42 +973,7 @@ public class BaseNoGui { } static public LibraryList scanLibraries(List folders) throws IOException { - LibraryList res = new LibraryList(); - 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; + return librariesIndexer.scanLibraries(folders); } static public void selectBoard(TargetBoard targetBoard) { diff --git a/arduino-core/src/processing/app/debug/Compiler.java b/arduino-core/src/processing/app/debug/Compiler.java index dd5d7128f..93e9e699c 100644 --- a/arduino-core/src/processing/app/debug/Compiler.java +++ b/arduino-core/src/processing/app/debug/Compiler.java @@ -52,10 +52,11 @@ import processing.app.SketchCode; import processing.app.SketchData; import processing.app.helpers.*; import processing.app.helpers.filefilters.OnlyDirs; -import processing.app.packages.Library; import processing.app.packages.LibraryList; import processing.app.preproc.PdePreprocessor; import processing.app.legacy.PApplet; +import processing.app.packages.LegacyUserLibrary; +import processing.app.packages.UserLibrary; public class Compiler implements MessageConsumer { @@ -361,11 +362,15 @@ public class Compiler implements MessageConsumer { includeFolders.add(prefs.getFile("build.core.path")); if (prefs.getFile("build.variant.path") != null) includeFolders.add(prefs.getFile("build.variant.path")); - for (Library lib : importedLibraries) { - if (verbose) + for (UserLibrary lib : importedLibraries) { + if (verbose) { + String legacy = ""; + if (lib instanceof LegacyUserLibrary) + legacy = "(legacy)"; System.out.println(I18n .format(_("Using library {0} in folder: {1} {2}"), lib.getName(), - lib.getFolder(), lib.isLegacy() ? "(legacy)" : "")); + lib.getInstalledFolder(), legacy)); + } includeFolders.add(lib.getSrcFolder()); } if (verbose) @@ -377,7 +382,7 @@ public class Compiler implements MessageConsumer { String[] overrides = prefs.get("architecture.override_check").split(","); archs.addAll(Arrays.asList(overrides)); } - for (Library lib : importedLibraries) { + for (UserLibrary lib : importedLibraries) { if (!lib.supportsArchitecture(archs)) { System.err.println(I18n .format(_("WARNING: library {0} claims to run on {1} " @@ -890,21 +895,21 @@ public class Compiler implements MessageConsumer { // 2. compile the libraries, outputting .o files to: // // void compileLibraries(List includeFolders) throws RunnerException, PreferencesMapException { - for (Library lib : importedLibraries) { + for (UserLibrary lib : importedLibraries) { compileLibrary(lib, includeFolders); } } - private void compileLibrary(Library lib, List includeFolders) + private void compileLibrary(UserLibrary lib, List includeFolders) throws RunnerException, PreferencesMapException { File libFolder = lib.getSrcFolder(); File libBuildFolder = prefs.getFile(("build.path"), lib.getName()); - + if (lib.useRecursion()) { // libBuildFolder == {build.path}/LibName // libFolder == {lib.path}/src recursiveCompileFilesInFolder(libBuildFolder, libFolder, includeFolders); - + } else { // libFolder == {lib.path}/ // utilityFolder == {lib.path}/utility @@ -912,11 +917,11 @@ public class Compiler implements MessageConsumer { // utilityBuildFolder == {build.path}/LibName/utility File utilityFolder = new File(libFolder, "utility"); File utilityBuildFolder = new File(libBuildFolder, "utility"); - + includeFolders.add(utilityFolder); compileFilesInFolder(libBuildFolder, libFolder, includeFolders); compileFilesInFolder(utilityBuildFolder, utilityFolder, includeFolders); - + // other libraries should not see this library's utility/ folder includeFolders.remove(utilityFolder); } @@ -1162,7 +1167,7 @@ public class Compiler implements MessageConsumer { importedLibraries = new LibraryList(); for (String item : preprocessor.getExtraImports()) { - Library lib = BaseNoGui.importToLibraryTable.get(item); + UserLibrary lib = BaseNoGui.importToLibraryTable.get(item); if (lib != null && !importedLibraries.contains(lib)) { importedLibraries.add(lib); } diff --git a/arduino-core/src/processing/app/packages/LegacyUserLibrary.java b/arduino-core/src/processing/app/packages/LegacyUserLibrary.java new file mode 100644 index 000000000..c5cf6284b --- /dev/null +++ b/arduino-core/src/processing/app/packages/LegacyUserLibrary.java @@ -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 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 getRequires() { + return null; + } + + @Override + public String toString() { + String res = "LegacyLibrary:"; + res += " (name=" + name + ")"; + return res; + } + + @Override + public String getSupportLevel() { + return "Unsupported"; + } +} diff --git a/arduino-core/src/processing/app/packages/LibraryList.java b/arduino-core/src/processing/app/packages/LibraryList.java index 343ff4bde..7bb5ec9f7 100644 --- a/arduino-core/src/processing/app/packages/LibraryList.java +++ b/arduino-core/src/processing/app/packages/LibraryList.java @@ -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; import java.io.File; @@ -8,7 +36,7 @@ import java.util.Collections; import processing.app.helpers.FileUtils; @SuppressWarnings("serial") -public class LibraryList extends ArrayList { +public class LibraryList extends ArrayList { public LibraryList(LibraryList libs) { super(libs); @@ -18,52 +46,33 @@ public class LibraryList extends ArrayList { super(); } - public Library getByName(String name) { - for (Library l : this) + public UserLibrary getByName(String name) { + for (UserLibrary l : this) if (l.getName().equals(name)) return l; return null; } - public void addOrReplace(Library lib) { - Library l = getByName(lib.getName()); + public void addOrReplace(UserLibrary lib) { + UserLibrary l = getByName(lib.getName()); if (l != null) remove(l); add(lib); } - public void addOrReplaceAll(Collection c) { - for (Library l : c) + public void addOrReplaceAll(Collection c) { + for (UserLibrary l : c) addOrReplace(l); } public void sort() { - Collections.sort(this, Library.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; + Collections.sort(this, UserLibrary.CASE_INSENSITIVE_ORDER); } public LibraryList filterLibrariesInSubfolder(File subFolder) { LibraryList res = new LibraryList(); - for (Library lib : this) - if (FileUtils.isSubDirectory(subFolder, lib.getFolder())) + for (UserLibrary lib : this) + if (FileUtils.isSubDirectory(subFolder, lib.getInstalledFolder())) res.add(lib); return res; } diff --git a/arduino-core/src/processing/app/packages/Library.java b/arduino-core/src/processing/app/packages/UserLibrary.java similarity index 66% rename from arduino-core/src/processing/app/packages/Library.java rename to arduino-core/src/processing/app/packages/UserLibrary.java index bf69c4edd..1caaaf276 100644 --- a/arduino-core/src/processing/app/packages/Library.java +++ b/arduino-core/src/processing/app/packages/UserLibrary.java @@ -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; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; -import java.util.Comparator; import java.util.List; import processing.app.helpers.FileUtils; 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 version; @@ -18,15 +47,10 @@ public class Library { private String maintainer; private String sentence; private String paragraph; - private String url; + private String website; private String category; private String license; private List architectures; - private File folder; - private boolean isLegacy; - - private enum LibraryLayout { FLAT, RECURSIVE }; - private LibraryLayout layout; private static final List MANDATORY_PROPERTIES = Arrays .asList(new String[] { "name", "version", "author", "maintainer", @@ -37,25 +61,7 @@ public class Library { "Device Control", "Timing", "Data Storage", "Data Processing", "Other", "Uncategorized" }); - /** - * 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 { + public static UserLibrary create(File libFolder) throws IOException { // Parse metadata File propertiesFile = new File(libFolder, "library.properties"); PreferencesMap properties = new PreferencesMap(); @@ -132,101 +138,59 @@ public class Library { if (license == null) license = "Unspecified"; - Library res = new Library(); - res.folder = libFolder; + UserLibrary res = new UserLibrary(); + res.setInstalledFolder(libFolder); + res.setInstalled(true); res.name = properties.get("name").trim(); res.version = properties.get("version").trim(); res.author = properties.get("author").trim(); res.maintainer = properties.get("maintainer").trim(); res.sentence = properties.get("sentence").trim(); res.paragraph = properties.get("paragraph").trim(); - res.url = properties.get("url").trim(); + res.website = properties.get("url").trim(); res.category = category.trim(); res.license = license.trim(); res.architectures = archs; - res.isLegacy = false; res.layout = layout; return res; } - private static Library createLegacyLibrary(File libFolder) { - // 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 true 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 true 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 reqArchs) { - if (reqArchs.contains("*")) - return true; - for (String reqArch : reqArchs) - if (supportsArchitecture(reqArch)) - return true; - return false; - } - - public static final Comparator CASE_INSENSITIVE_ORDER = new Comparator() { - @Override - public int compare(Library o1, Library o2) { - return o1.getName().compareToIgnoreCase(o2.getName()); - } - }; - + @Override public String getName() { return name; } - public File getFolder() { - return folder; - } - + @Override public List getArchitectures() { return architectures; } + @Override public String getAuthor() { return author; } + @Override public String getParagraph() { return paragraph; } + @Override public String getSentence() { return sentence; } - public String getUrl() { - return url; + @Override + public String getWebsite() { + return website; } + @Override public String getCategory() { return category; } + @Override public String getLicense() { return license; } @@ -235,31 +199,60 @@ public class Library { return CATEGORIES; } + @Override public String getVersion() { return version; } + @Override public String getMaintainer() { return maintainer; } - public boolean useRecursion() { - return (layout == LibraryLayout.RECURSIVE); + @Override + 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 getRequires() { + return null; + } + + protected enum LibraryLayout { + FLAT, RECURSIVE + }; + + protected LibraryLayout layout; + public File getSrcFolder() { switch (layout) { - case FLAT: - return folder; - case RECURSIVE: - return new File(folder, "src"); - default: - return null; // Keep compiler happy :-( + case FLAT: + return getInstalledFolder(); + case RECURSIVE: + return new File(getInstalledFolder(), "src"); + default: + return null; // Keep compiler happy :-( } } - public boolean isLegacy() { - return isLegacy; + public boolean useRecursion() { + return (layout == LibraryLayout.RECURSIVE); } @Override @@ -271,8 +264,13 @@ public class Library { res += " (maintainer=" + maintainer + ")"; res += " (sentence=" + sentence + ")"; res += " (paragraph=" + paragraph + ")"; - res += " (url=" + url + ")"; + res += " (url=" + website + ")"; res += " (architectures=" + architectures + ")"; return res; } + + @Override + public String getSupportLevel() { + return "Unsupported"; + } }