mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-16 11:21:18 +03:00
Merge branch 'master' into esp8266
* master: (414 commits) Don't export sketch if the underlying core does not support it. Fixes #3171 RSyntaxTextArea: using a modified version, tracked at https://github.com/arduino/RSyntaxTextArea. Fixes #3099 Updated keywords.txt New editor on MacOSX: since CMD+J is known as "jump to selection" and the editor has no such feature, CMD+J is disabled on mac. See #3098 Old Preferences class remains for backwards compatibility as a delegate for PreferencesData New Preferences window: renders fine on every OS and it's easier to adapt using NetBeans as visual editor. Fixes #3140 Remove spawn from exec command Removed redundant call to File.deleteIfExists() Removed buggy redundant check in FileUtils.deleteIfExists() Restored current line/current selected lines display on lower left of the IDE. Fixes #3134 Updated cursor.ino New editor on MacOSX: restored CMD+E for finding selected text New editor on MacOSX: CMD+UP/DOWN moves cursor to start or end of sketch. See #3098 New editor on MacOSX: CMD+BACKSPACE deletes current line until cursor position, ALT+BACKSPACE deletes previous word. See #3098 ArduinoIDE is in the default package. Removed Fixes #2969: Fix Uncategorized warning message New editor: ALT+ BACKSPACE deletes next word (OSX only). See #3098 New editor: ALT+ UP/DOWN move current line only if "editor.advanced" (hidden pref) is true. Fixes #3101 New editor: mark occurrences enable when "editor.advanced" (hidden pref) is true. Fixes #3102 ... Conflicts: .gitignore build/build.xml hardware/esp8266com/esp8266/libraries/ESP8266WiFi/keywords.txt hardware/esp8266com/esp8266/libraries/ESP8266WiFi/library.properties hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h libraries/WiFi/README.adoc libraries/WiFi/src/WiFi.cpp libraries/WiFi/src/WiFiClient.cpp libraries/WiFi/src/WiFiClient.h libraries/WiFi/src/WiFiServer.cpp libraries/WiFi/src/WiFiUdp.cpp
This commit is contained in:
@ -9,5 +9,26 @@
|
||||
<classpathentry kind="lib" path="lib/jssc-2.8.0.jar"/>
|
||||
<classpathentry kind="lib" path="lib/jsch-0.1.50.jar"/>
|
||||
<classpathentry kind="lib" path="lib/commons-exec-1.1.jar"/>
|
||||
<classpathentry kind="lib" path="../app/lib/commons-codec-1.7.jar"/>
|
||||
<classpathentry kind="lib" path="../app/lib/commons-compress-1.8.jar"/>
|
||||
<classpathentry kind="lib" path="../app/lib/commons-exec-1.1.jar"/>
|
||||
<classpathentry kind="lib" path="../app/lib/commons-httpclient-3.1.jar"/>
|
||||
<classpathentry kind="lib" path="../app/lib/jackson-annotations-2.2.3.jar"/>
|
||||
<classpathentry kind="lib" path="../app/lib/jackson-core-2.2.3.jar"/>
|
||||
<classpathentry kind="lib" path="../app/lib/jackson-databind-2.2.3.jar"/>
|
||||
<classpathentry kind="lib" path="../app/lib/jackson-module-mrbean-2.2.3.jar"/>
|
||||
<classpathentry kind="lib" path="../app/lib/bcpg-jdk15on-152.jar"/>
|
||||
<classpathentry kind="lib" path="../app/lib/bcprov-jdk15on-152.jar"/>
|
||||
<classpathentry kind="lib" path="lib/bcpg-jdk15on-152.jar"/>
|
||||
<classpathentry kind="lib" path="lib/bcprov-jdk15on-152.jar"/>
|
||||
<classpathentry kind="lib" path="lib/commons-codec-1.7.jar"/>
|
||||
<classpathentry kind="lib" path="lib/commons-compress-1.8.jar"/>
|
||||
<classpathentry kind="lib" path="lib/commons-lang3-3.3.2.jar"/>
|
||||
<classpathentry kind="lib" path="lib/guava-18.0.jar"/>
|
||||
<classpathentry kind="lib" path="lib/jackson-annotations-2.2.3.jar"/>
|
||||
<classpathentry kind="lib" path="lib/jackson-core-2.2.3.jar"/>
|
||||
<classpathentry kind="lib" path="lib/jackson-databind-2.2.3.jar"/>
|
||||
<classpathentry kind="lib" path="lib/jackson-module-mrbean-2.2.3.jar"/>
|
||||
<classpathentry kind="lib" path="lib/java-semver-0.8.0.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
16
arduino-core/.editorconfig
Normal file
16
arduino-core/.editorconfig
Normal file
@ -0,0 +1,16 @@
|
||||
# EditorConfig is awesome: http://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
charset = utf-8
|
||||
|
||||
[*.{md,adoc}]
|
||||
indent_style = space
|
||||
trim_trailing_whitespace = false
|
BIN
arduino-core/lib/bcpg-jdk15on-152.jar
Normal file
BIN
arduino-core/lib/bcpg-jdk15on-152.jar
Normal file
Binary file not shown.
BIN
arduino-core/lib/bcprov-jdk15on-152.jar
Normal file
BIN
arduino-core/lib/bcprov-jdk15on-152.jar
Normal file
Binary file not shown.
BIN
arduino-core/lib/commons-codec-1.7.jar
Normal file
BIN
arduino-core/lib/commons-codec-1.7.jar
Normal file
Binary file not shown.
BIN
arduino-core/lib/commons-compress-1.8.jar
Normal file
BIN
arduino-core/lib/commons-compress-1.8.jar
Normal file
Binary file not shown.
202
arduino-core/lib/commons-compress.LICENSE.ASL-2.0.txt
Normal file
202
arduino-core/lib/commons-compress.LICENSE.ASL-2.0.txt
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
BIN
arduino-core/lib/commons-lang3-3.3.2.jar
Normal file
BIN
arduino-core/lib/commons-lang3-3.3.2.jar
Normal file
Binary file not shown.
202
arduino-core/lib/commons-lang3.LICENSE.ASL-2.0.txt
Normal file
202
arduino-core/lib/commons-lang3.LICENSE.ASL-2.0.txt
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
203
arduino-core/lib/guava-18.0.LICENSE.ASL-2.0.txt
Normal file
203
arduino-core/lib/guava-18.0.LICENSE.ASL-2.0.txt
Normal file
@ -0,0 +1,203 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
BIN
arduino-core/lib/guava-18.0.jar
Normal file
BIN
arduino-core/lib/guava-18.0.jar
Normal file
Binary file not shown.
BIN
arduino-core/lib/jackson-annotations-2.2.3.jar
Normal file
BIN
arduino-core/lib/jackson-annotations-2.2.3.jar
Normal file
Binary file not shown.
BIN
arduino-core/lib/jackson-core-2.2.3.jar
Normal file
BIN
arduino-core/lib/jackson-core-2.2.3.jar
Normal file
Binary file not shown.
BIN
arduino-core/lib/jackson-databind-2.2.3.jar
Normal file
BIN
arduino-core/lib/jackson-databind-2.2.3.jar
Normal file
Binary file not shown.
BIN
arduino-core/lib/jackson-module-mrbean-2.2.3.jar
Normal file
BIN
arduino-core/lib/jackson-module-mrbean-2.2.3.jar
Normal file
Binary file not shown.
BIN
arduino-core/lib/java-semver-0.8.0.jar
Normal file
BIN
arduino-core/lib/java-semver-0.8.0.jar
Normal file
Binary file not shown.
0
arduino-core/lib/java-semver.LICENSE.MIT.txt
Normal file
0
arduino-core/lib/java-semver.LICENSE.MIT.txt
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* Copyright 2015 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;
|
||||
|
||||
public class DefaultUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
|
||||
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
System.err.println(t);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* Copyright 2015 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.contributions;
|
||||
|
||||
import cc.arduino.contributions.packages.DownloadableContribution;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class DownloadableContributionBuiltInAtTheBottomComparator implements Comparator<DownloadableContribution> {
|
||||
@Override
|
||||
public int compare(DownloadableContribution p1, DownloadableContribution p2) {
|
||||
if (p1.isReadOnly() == p2.isReadOnly()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return p1.isReadOnly() ? 1 : -1;
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* Copyright 2015 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.contributions;
|
||||
|
||||
import cc.arduino.contributions.packages.DownloadableContribution;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class DownloadableContributionVersionComparator implements Comparator<DownloadableContribution> {
|
||||
|
||||
private final VersionComparator versionComparator;
|
||||
|
||||
public DownloadableContributionVersionComparator() {
|
||||
versionComparator = new VersionComparator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(DownloadableContribution lib1, DownloadableContribution lib2) {
|
||||
return versionComparator.compare(lib1.getParsedVersion(), lib2.getParsedVersion());
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
|
||||
*/
|
||||
|
||||
package cc.arduino.contributions;
|
||||
|
||||
import org.apache.commons.compress.utils.IOUtils;
|
||||
import org.bouncycastle.openpgp.*;
|
||||
import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
|
||||
import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class GPGDetachedSignatureVerifier {
|
||||
|
||||
private String keyId;
|
||||
|
||||
public GPGDetachedSignatureVerifier() {
|
||||
this("7F294291");
|
||||
}
|
||||
|
||||
public GPGDetachedSignatureVerifier(String keyId) {
|
||||
this.keyId = keyId;
|
||||
}
|
||||
|
||||
public boolean verify(File signedFile, File signature, File publicKey) throws IOException, PGPException {
|
||||
PGPPublicKey pgpPublicKey = readPublicKey(publicKey, keyId);
|
||||
|
||||
FileInputStream signatureInputStream = null;
|
||||
FileInputStream signedFileInputStream = null;
|
||||
try {
|
||||
signatureInputStream = new FileInputStream(signature);
|
||||
PGPObjectFactory pgpObjectFactory = new PGPObjectFactory(signatureInputStream, new BcKeyFingerprintCalculator());
|
||||
|
||||
Object nextObject;
|
||||
try {
|
||||
nextObject = pgpObjectFactory.nextObject();
|
||||
if (!(nextObject instanceof PGPSignatureList)) {
|
||||
return false;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
PGPSignatureList pgpSignatureList = (PGPSignatureList) nextObject;
|
||||
assert pgpSignatureList.size() == 1;
|
||||
PGPSignature pgpSignature = pgpSignatureList.get(0);
|
||||
|
||||
pgpSignature.init(new BcPGPContentVerifierBuilderProvider(), pgpPublicKey);
|
||||
signedFileInputStream = new FileInputStream(signedFile);
|
||||
pgpSignature.update(IOUtils.toByteArray(signedFileInputStream));
|
||||
|
||||
return pgpSignature.verify();
|
||||
} finally {
|
||||
if (signatureInputStream != null) {
|
||||
signatureInputStream.close();
|
||||
}
|
||||
if (signedFileInputStream != null) {
|
||||
signedFileInputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private PGPPublicKey readPublicKey(File file, String keyId) throws IOException, PGPException {
|
||||
InputStream keyIn = null;
|
||||
try {
|
||||
keyIn = new BufferedInputStream(new FileInputStream(file));
|
||||
return readPublicKey(keyIn, keyId);
|
||||
} finally {
|
||||
if (keyIn != null) {
|
||||
keyIn.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private PGPPublicKey readPublicKey(InputStream input, String keyId) throws IOException, PGPException {
|
||||
PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(input), new BcKeyFingerprintCalculator());
|
||||
|
||||
Iterator keyRingIter = pgpPub.getKeyRings();
|
||||
while (keyRingIter.hasNext()) {
|
||||
PGPPublicKeyRing keyRing = (PGPPublicKeyRing) keyRingIter.next();
|
||||
|
||||
Iterator keyIter = keyRing.getPublicKeys();
|
||||
while (keyIter.hasNext()) {
|
||||
PGPPublicKey key = (PGPPublicKey) keyIter.next();
|
||||
|
||||
if (Long.toHexString(key.getKeyID()).toUpperCase().endsWith(keyId)) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Can't find encryption key in key ring.");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package cc.arduino.contributions;
|
||||
|
||||
import processing.app.I18n;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
|
||||
public class SignatureVerificationFailedException extends Exception {
|
||||
|
||||
public SignatureVerificationFailedException(String filename) {
|
||||
super(I18n.format(_("{0} file signature verification failed"), filename));
|
||||
}
|
||||
|
||||
public SignatureVerificationFailedException(String filename, Throwable cause) {
|
||||
super(I18n.format(_("{0} file signature verification failed"), filename), cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.contributions;
|
||||
|
||||
import com.github.zafarkhaja.semver.Version;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class VersionComparator implements Comparator<String> {
|
||||
|
||||
@Override
|
||||
public int compare(String a, String b) {
|
||||
// null is always less than any other value
|
||||
if (a == null && b == null)
|
||||
return 0;
|
||||
if (a == null)
|
||||
return -1;
|
||||
if (b == null)
|
||||
return 1;
|
||||
|
||||
Version versionA = VersionHelper.valueOf(a);
|
||||
Version versionB = VersionHelper.valueOf(b);
|
||||
|
||||
return versionA.compareTo(versionB);
|
||||
}
|
||||
|
||||
public boolean greaterThan(String a, String b) {
|
||||
// null is always less than any other value
|
||||
if (a == null && b == null) {
|
||||
return false;
|
||||
}
|
||||
if (a == null) {
|
||||
return false;
|
||||
}
|
||||
if (b == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Version versionA = VersionHelper.valueOf(a);
|
||||
Version versionB = VersionHelper.valueOf(b);
|
||||
|
||||
return versionA.greaterThan(versionB);
|
||||
}
|
||||
|
||||
}
|
57
arduino-core/src/cc/arduino/contributions/VersionHelper.java
Normal file
57
arduino-core/src/cc/arduino/contributions/VersionHelper.java
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* Copyright 2015 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.contributions;
|
||||
|
||||
import com.github.zafarkhaja.semver.Version;
|
||||
|
||||
public class VersionHelper {
|
||||
|
||||
public static Version valueOf(String ver) {
|
||||
if (ver == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
String[] verParts = ver.split("\\.");
|
||||
if (verParts.length < 3) {
|
||||
if (verParts.length == 2) {
|
||||
return Version.forIntegers(Integer.valueOf(verParts[0]), Integer.valueOf(verParts[1]));
|
||||
} else {
|
||||
return Version.forIntegers(Integer.valueOf(verParts[0]));
|
||||
}
|
||||
} else {
|
||||
return Version.valueOf(ver);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("Invalid version found: " + ver);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* Copyright 2015 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.contributions.filters;
|
||||
|
||||
import cc.arduino.contributions.packages.DownloadableContribution;
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
public class BuiltInPredicate implements Predicate<DownloadableContribution> {
|
||||
|
||||
@Override
|
||||
public boolean apply(DownloadableContribution input) {
|
||||
return input.isReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof BuiltInPredicate;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* Copyright 2015 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.contributions.filters;
|
||||
|
||||
import cc.arduino.contributions.packages.DownloadableContribution;
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
public class DownloadableContributionWithVersionPredicate implements Predicate<DownloadableContribution> {
|
||||
private final String version;
|
||||
|
||||
public DownloadableContributionWithVersionPredicate(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(DownloadableContribution contribution) {
|
||||
return version.equals(contribution.getParsedVersion());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* Copyright 2015 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.contributions.filters;
|
||||
|
||||
import cc.arduino.contributions.packages.DownloadableContribution;
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
public class InstalledPredicate implements Predicate<DownloadableContribution> {
|
||||
@Override
|
||||
public boolean apply(DownloadableContribution input) {
|
||||
return input.isInstalled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof DownloadableContribution;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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.contributions.libraries;
|
||||
|
||||
import cc.arduino.contributions.packages.DownloadableContribution;
|
||||
import processing.app.I18n;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
|
||||
public abstract class ContributedLibrary extends DownloadableContribution {
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
public abstract String getMaintainer();
|
||||
|
||||
public abstract String getAuthor();
|
||||
|
||||
public abstract String getWebsite();
|
||||
|
||||
public abstract String getCategory();
|
||||
|
||||
public abstract void setCategory(String category);
|
||||
|
||||
public abstract String getLicense();
|
||||
|
||||
public abstract String getParagraph();
|
||||
|
||||
public abstract String getSentence();
|
||||
|
||||
public abstract List<String> getArchitectures();
|
||||
|
||||
public abstract List<String> getTypes();
|
||||
|
||||
public abstract List<ContributedLibraryReference> getRequires();
|
||||
|
||||
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() {
|
||||
return I18n.format(_("Version {0}"), getParsedVersion());
|
||||
}
|
||||
|
||||
public String info() {
|
||||
String res = "";
|
||||
res += " ContributedLibrary : " + getName() + "\n";
|
||||
res += " author : " + getAuthor() + "\n";
|
||||
res += " maintainer : " + getMaintainer() + "\n";
|
||||
res += " version : " + getParsedVersion() + "\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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof ContributedLibrary)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String thisVersion = getParsedVersion();
|
||||
String otherVersion = ((ContributedLibrary) obj).getParsedVersion();
|
||||
|
||||
boolean versionEquals = thisVersion == otherVersion || (thisVersion != null && otherVersion != null && thisVersion.equals(otherVersion));
|
||||
|
||||
String thisName = getName();
|
||||
String otherName = ((ContributedLibrary) obj).getName();
|
||||
|
||||
boolean nameEquals = thisName == null || otherName == null || thisName.equals(otherName);
|
||||
|
||||
return versionEquals && nameEquals;
|
||||
}
|
||||
}
|
@ -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.contributions.libraries;
|
||||
|
||||
public abstract class ContributedLibraryReference {
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
public abstract String getMaintainer();
|
||||
|
||||
public abstract String getVersion();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName() + " " + getVersion() + " (" + getMaintainer() + ")";
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.contributions.libraries;
|
||||
|
||||
import cc.arduino.contributions.DownloadableContributionBuiltInAtTheBottomComparator;
|
||||
import cc.arduino.contributions.filters.InstalledPredicate;
|
||||
import cc.arduino.contributions.libraries.filters.LibraryWithNamePredicate;
|
||||
import com.google.common.collect.Collections2;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public abstract class LibrariesIndex {
|
||||
|
||||
public abstract List<ContributedLibrary> getLibraries();
|
||||
|
||||
public List<ContributedLibrary> find(final String name) {
|
||||
return new LinkedList<ContributedLibrary>(Collections2.filter(getLibraries(), new LibraryWithNamePredicate(name)));
|
||||
}
|
||||
|
||||
public ContributedLibrary find(String name, String version) {
|
||||
if (name == null || version == null) {
|
||||
return null;
|
||||
}
|
||||
for (ContributedLibrary lib : find(name)) {
|
||||
if (version.equals(lib.getParsedVersion())) {
|
||||
return lib;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (ContributedLibrary library : getLibraries()) {
|
||||
sb.append(library.toString());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public List<String> getCategories() {
|
||||
List<String> categories = new LinkedList<String>();
|
||||
for (ContributedLibrary lib : getLibraries()) {
|
||||
if (lib.getCategory() != null && !categories.contains(lib.getCategory())) {
|
||||
categories.add(lib.getCategory());
|
||||
}
|
||||
}
|
||||
Collections.sort(categories);
|
||||
|
||||
return categories;
|
||||
}
|
||||
|
||||
public List<String> getTypes() {
|
||||
Collection<String> typesAccumulator = new HashSet<String>();
|
||||
for (ContributedLibrary lib : getLibraries()) {
|
||||
if (lib.getTypes() != null) {
|
||||
typesAccumulator.addAll(lib.getTypes());
|
||||
}
|
||||
}
|
||||
|
||||
List<String> types = new LinkedList<String>(typesAccumulator);
|
||||
Collections.sort(types);
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
public ContributedLibrary getInstalled(String name) {
|
||||
List<ContributedLibrary> installedReleases = new LinkedList<ContributedLibrary>(Collections2.filter(find(name), new InstalledPredicate()));
|
||||
Collections.sort(installedReleases, new DownloadableContributionBuiltInAtTheBottomComparator());
|
||||
|
||||
if (installedReleases.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return installedReleases.get(0);
|
||||
}
|
||||
}
|
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* 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.contributions.libraries;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.module.mrbean.MrBeanModule;
|
||||
import processing.app.BaseNoGui;
|
||||
import processing.app.I18n;
|
||||
import processing.app.helpers.FileUtils;
|
||||
import processing.app.helpers.filefilters.OnlyDirs;
|
||||
import processing.app.packages.LegacyUserLibrary;
|
||||
import processing.app.packages.LibraryList;
|
||||
import processing.app.packages.UserLibrary;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
|
||||
public class LibrariesIndexer {
|
||||
|
||||
private LibrariesIndex index;
|
||||
private final LibraryList installedLibraries = new LibraryList();
|
||||
private final LibraryList installedLibrariesWithDuplicates = new LibraryList();
|
||||
private List<File> librariesFolders;
|
||||
private final File indexFile;
|
||||
private final File stagingFolder;
|
||||
private File sketchbookLibrariesFolder;
|
||||
|
||||
public LibrariesIndexer(File preferencesFolder) {
|
||||
indexFile = new File(preferencesFolder, "library_index.json");
|
||||
stagingFolder = new File(preferencesFolder, "staging" + File.separator +
|
||||
"libraries");
|
||||
}
|
||||
|
||||
public void parseIndex() throws IOException {
|
||||
parseIndex(indexFile);
|
||||
// TODO: resolve libraries inner references
|
||||
}
|
||||
|
||||
private void parseIndex(File indexFile) throws IOException {
|
||||
InputStream indexIn = null;
|
||||
try {
|
||||
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, false);
|
||||
index = mapper.readValue(indexIn, LibrariesIndex.class);
|
||||
|
||||
for (ContributedLibrary library : index.getLibraries()) {
|
||||
if (library.getCategory() == null || "".equals(library.getCategory())) {
|
||||
library.setCategory("Uncategorized");
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (indexIn != null) {
|
||||
indexIn.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setLibrariesFolders(List<File> _librariesFolders) {
|
||||
librariesFolders = _librariesFolders;
|
||||
rescanLibraries();
|
||||
}
|
||||
|
||||
public void rescanLibraries() {
|
||||
// Clear all installed flags
|
||||
installedLibraries.clear();
|
||||
installedLibrariesWithDuplicates.clear();
|
||||
for (ContributedLibrary lib : index.getLibraries())
|
||||
lib.setInstalled(false);
|
||||
|
||||
// Rescan libraries
|
||||
for (File folder : librariesFolders)
|
||||
scanInstalledLibraries(folder, folder.equals(sketchbookLibrariesFolder));
|
||||
}
|
||||
|
||||
private void scanInstalledLibraries(File folder, boolean isSketchbook) {
|
||||
File list[] = folder.listFiles(OnlyDirs.ONLY_DIRS);
|
||||
// if a bad folder or something like that, this might come back null
|
||||
if (list == null)
|
||||
return;
|
||||
|
||||
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 {
|
||||
scanLibrary(subfolder, isSketchbook);
|
||||
} catch (IOException e) {
|
||||
System.out.println(I18n.format(_("Invalid library found in {0}: {1}"), subfolder, e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void scanLibrary(File folder, boolean isSketchbook) throws IOException {
|
||||
boolean readOnly = !FileUtils.isSubDirectory(sketchbookLibrariesFolder, folder);
|
||||
|
||||
// A library is considered "legacy" if it doesn't contains
|
||||
// a file called "library.properties"
|
||||
File check = new File(folder, "library.properties");
|
||||
if (!check.exists() || !check.isFile()) {
|
||||
// Create a legacy library and exit
|
||||
LegacyUserLibrary lib = LegacyUserLibrary.create(folder);
|
||||
lib.setReadOnly(readOnly);
|
||||
installedLibraries.addOrReplace(lib);
|
||||
if (isSketchbook) {
|
||||
installedLibrariesWithDuplicates.add(lib);
|
||||
} else {
|
||||
installedLibrariesWithDuplicates.addOrReplace(lib);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a regular library
|
||||
UserLibrary lib = UserLibrary.create(folder);
|
||||
lib.setReadOnly(readOnly);
|
||||
installedLibraries.addOrReplace(lib);
|
||||
if (isSketchbook) {
|
||||
installedLibrariesWithDuplicates.add(lib);
|
||||
} else {
|
||||
installedLibrariesWithDuplicates.addOrReplace(lib);
|
||||
}
|
||||
|
||||
// Check if we can find the same library in the index
|
||||
// and mark it as installed
|
||||
ContributedLibrary foundLib = index.find(lib.getName(), lib.getParsedVersion());
|
||||
if (foundLib != null) {
|
||||
foundLib.setInstalled(true);
|
||||
foundLib.setInstalledFolder(folder);
|
||||
foundLib.setReadOnly(readOnly);
|
||||
lib.setTypes(foundLib.getTypes());
|
||||
}
|
||||
|
||||
if (lib.isReadOnly() && lib.getTypes() == null && !lib.getDeclaredTypes().isEmpty()) {
|
||||
lib.setTypes(lib.getDeclaredTypes());
|
||||
}
|
||||
|
||||
if (lib.getTypes() == null) {
|
||||
lib.setTypes(Arrays.asList("Contributed"));
|
||||
}
|
||||
}
|
||||
|
||||
public LibrariesIndex getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public LibraryList getInstalledLibraries() {
|
||||
return installedLibraries;
|
||||
}
|
||||
|
||||
// Same as getInstalledLibraries(), but allow duplicates between
|
||||
// builtin+package libraries and sketchbook installed libraries.
|
||||
// However, do not report duplicates among builtin and packages, to
|
||||
// allow any package to override builtin libraries without being
|
||||
// reported as duplicates.
|
||||
public LibraryList getInstalledLibrariesWithDuplicates() {
|
||||
return installedLibrariesWithDuplicates;
|
||||
}
|
||||
|
||||
public File getStagingFolder() {
|
||||
return stagingFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sketchbook library folder. <br />
|
||||
* New libraries will be installed here. <br />
|
||||
* Libraries not found on this folder will be marked as read-only.
|
||||
*
|
||||
* @param folder
|
||||
*/
|
||||
public void setSketchbookLibrariesFolder(File folder) {
|
||||
this.sketchbookLibrariesFolder = folder;
|
||||
}
|
||||
|
||||
public File getSketchbookLibrariesFolder() {
|
||||
return sketchbookLibrariesFolder;
|
||||
}
|
||||
|
||||
public File getIndexFile() {
|
||||
return indexFile;
|
||||
}
|
||||
}
|
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* Copyright 2015 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.contributions.libraries;
|
||||
|
||||
import cc.arduino.contributions.packages.DownloadableContributionsDownloader;
|
||||
import cc.arduino.utils.ArchiveExtractor;
|
||||
import cc.arduino.utils.MultiStepProgress;
|
||||
import cc.arduino.utils.Progress;
|
||||
import processing.app.BaseNoGui;
|
||||
import processing.app.I18n;
|
||||
import processing.app.helpers.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
|
||||
public class LibraryInstaller {
|
||||
|
||||
private static final String LIBRARY_INDEX_URL;
|
||||
|
||||
static {
|
||||
String externalLibraryIndexUrl = System.getProperty("LIBRARY_INDEX_URL");
|
||||
if (externalLibraryIndexUrl != null && !"".equals(externalLibraryIndexUrl)) {
|
||||
LIBRARY_INDEX_URL = externalLibraryIndexUrl;
|
||||
} else {
|
||||
LIBRARY_INDEX_URL = "http://downloads.arduino.cc/libraries/library_index.json";
|
||||
}
|
||||
}
|
||||
|
||||
private final LibrariesIndexer indexer;
|
||||
private final DownloadableContributionsDownloader downloader;
|
||||
|
||||
public LibraryInstaller(LibrariesIndexer _indexer) {
|
||||
indexer = _indexer;
|
||||
File stagingFolder = _indexer.getStagingFolder();
|
||||
downloader = new DownloadableContributionsDownloader(stagingFolder) {
|
||||
@Override
|
||||
protected void onProgress(Progress progress) {
|
||||
LibraryInstaller.this.onProgress(progress);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void updateIndex() throws Exception {
|
||||
final MultiStepProgress progress = new MultiStepProgress(2);
|
||||
|
||||
// Step 1: Download index
|
||||
URL url = new URL(LIBRARY_INDEX_URL);
|
||||
File outputFile = indexer.getIndexFile();
|
||||
File tmpFile = new File(outputFile.getAbsolutePath() + ".tmp");
|
||||
try {
|
||||
downloader.download(url, tmpFile, progress,
|
||||
_("Downloading libraries index..."));
|
||||
} catch (InterruptedException e) {
|
||||
// Download interrupted... just exit
|
||||
return;
|
||||
}
|
||||
progress.stepDone();
|
||||
|
||||
// TODO: Check downloaded index
|
||||
|
||||
// Replace old index with the updated one
|
||||
if (outputFile.exists())
|
||||
outputFile.delete();
|
||||
if (!tmpFile.renameTo(outputFile))
|
||||
throw new Exception(
|
||||
_("An error occurred while updating libraries index!"));
|
||||
|
||||
// Step 2: Rescan index
|
||||
rescanLibraryIndex(progress);
|
||||
}
|
||||
|
||||
public void install(ContributedLibrary lib, ContributedLibrary replacedLib) throws Exception {
|
||||
if (lib.isInstalled()) {
|
||||
System.out.println(I18n.format(_("Library is already installed: {0} version {1}"), lib.getName(), lib.getParsedVersion()));
|
||||
return;
|
||||
}
|
||||
|
||||
final MultiStepProgress progress = new MultiStepProgress(3);
|
||||
|
||||
// Step 1: Download library
|
||||
try {
|
||||
downloader.download(lib, progress, I18n.format(_("Downloading library: {0}"), lib.getName()));
|
||||
} catch (InterruptedException e) {
|
||||
// Download interrupted... just exit
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Extract to temporary folders and move to the final destination only
|
||||
// once everything is successfully unpacked. If the operation fails remove
|
||||
// all the temporary folders and abort installation.
|
||||
|
||||
// Step 2: Unpack library on the correct location
|
||||
progress.setStatus(I18n.format(_("Installing library: {0}"), lib.getName()));
|
||||
onProgress(progress);
|
||||
File libsFolder = indexer.getSketchbookLibrariesFolder();
|
||||
File tmpFolder = FileUtils.createTempFolderIn(libsFolder);
|
||||
try {
|
||||
new ArchiveExtractor(BaseNoGui.getPlatform()).extract(lib.getDownloadedFile(), tmpFolder, 1);
|
||||
} catch (Exception e) {
|
||||
if (tmpFolder.exists())
|
||||
FileUtils.recursiveDelete(tmpFolder);
|
||||
}
|
||||
progress.stepDone();
|
||||
|
||||
// Step 3: Remove replaced library and move installed one to the correct location
|
||||
// TODO: Fix progress bar...
|
||||
remove(replacedLib);
|
||||
File destFolder = new File(libsFolder, lib.getName().replaceAll(" ", "_"));
|
||||
tmpFolder.renameTo(destFolder);
|
||||
progress.stepDone();
|
||||
|
||||
// Step 4: Rescan index
|
||||
rescanLibraryIndex(progress);
|
||||
}
|
||||
|
||||
public void remove(ContributedLibrary lib) throws IOException {
|
||||
if (lib == null || lib.isReadOnly()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final MultiStepProgress progress = new MultiStepProgress(2);
|
||||
|
||||
// Step 1: Remove library
|
||||
progress.setStatus(I18n.format(_("Removing library: {0}"), lib.getName()));
|
||||
onProgress(progress);
|
||||
FileUtils.recursiveDelete(lib.getInstalledFolder());
|
||||
progress.stepDone();
|
||||
|
||||
// Step 2: Rescan index
|
||||
rescanLibraryIndex(progress);
|
||||
}
|
||||
|
||||
private void rescanLibraryIndex(MultiStepProgress progress) {
|
||||
progress.setStatus(_("Updating list of installed libraries"));
|
||||
onProgress(progress);
|
||||
indexer.rescanLibraries();
|
||||
progress.stepDone();
|
||||
}
|
||||
|
||||
protected void onProgress(Progress progress) {
|
||||
// Empty
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* Copyright 2015 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.contributions.libraries.filters;
|
||||
|
||||
import cc.arduino.contributions.libraries.ContributedLibrary;
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
public class LibraryWithNamePredicate implements Predicate<ContributedLibrary> {
|
||||
|
||||
private final String name;
|
||||
|
||||
public LibraryWithNamePredicate(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(ContributedLibrary contributedLibrary) {
|
||||
return name.equals(contributedLibrary.getName());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package cc.arduino.contributions.packages;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static final String DEFAULT_INDEX_FILE_NAME = "package_index.json";
|
||||
public static final List<String> PROTECTED_PACKAGE_NAMES = Arrays.asList("arduino", "Intel");
|
||||
public static final String PACKAGE_INDEX_URL;
|
||||
|
||||
public static final String PREFERENCES_BOARDS_MANAGER_ADDITIONAL_URLS = "boardsmanager.additional.urls";
|
||||
|
||||
static {
|
||||
String extenalPackageIndexUrl = System.getProperty("PACKAGE_INDEX_URL");
|
||||
if (extenalPackageIndexUrl != null && !"".equals(extenalPackageIndexUrl)) {
|
||||
PACKAGE_INDEX_URL = extenalPackageIndexUrl;
|
||||
} else {
|
||||
PACKAGE_INDEX_URL = "http://downloads.arduino.cc/packages/package_index.json";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.contributions.packages;
|
||||
|
||||
public interface ContributedBoard {
|
||||
|
||||
String getName();
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package cc.arduino.contributions.packages;
|
||||
|
||||
public abstract class ContributedHelp {
|
||||
|
||||
public abstract String getOnline();
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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.contributions.packages;
|
||||
|
||||
import cc.arduino.contributions.VersionComparator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ContributedPackage {
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
public abstract String getMaintainer();
|
||||
|
||||
public abstract String getWebsiteURL();
|
||||
|
||||
public abstract String getEmail();
|
||||
|
||||
public abstract List<ContributedPlatform> getPlatforms();
|
||||
|
||||
public abstract List<ContributedTool> getTools();
|
||||
|
||||
public abstract ContributedHelp getHelp();
|
||||
|
||||
public ContributedPlatform findPlatform(String architecture, String version) {
|
||||
if (architecture == null || version == null) {
|
||||
return null;
|
||||
}
|
||||
for (ContributedPlatform platform : getPlatforms()) {
|
||||
if (platform.getArchitecture().equals(architecture) && version.equals(platform.getParsedVersion()))
|
||||
return platform;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ContributedTool findTool(String name, String version) {
|
||||
for (ContributedTool tool : getTools()) {
|
||||
if (tool.getName().equals(name) && tool.getVersion().equals(version))
|
||||
return tool;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String res;
|
||||
res = "Package name : " + getName() + "\n";
|
||||
res += " maintaner : " + getMaintainer() + " (" + getEmail() + ")\n";
|
||||
if (getPlatforms() != null) {
|
||||
for (ContributedPlatform plat : getPlatforms()) {
|
||||
res += "\n Plaform : name : " + plat.getName();
|
||||
if (plat.isInstalled()) {
|
||||
res += "\n " + plat;
|
||||
}
|
||||
res += "\n category : " + plat.getCategory();
|
||||
res += "\n architecture : " +
|
||||
plat.getArchitecture() + " " + plat.getParsedVersion() + "\n";
|
||||
if (plat.getToolsDependencies() != null)
|
||||
for (ContributedToolReference t : plat.getToolsDependencies()) {
|
||||
res += " tool dep : " + t.getName() + " " +
|
||||
t.getVersion() + "\n";
|
||||
}
|
||||
if (plat.getBoards() != null)
|
||||
for (ContributedBoard board : plat.getBoards())
|
||||
res += " board : " + board.getName() +
|
||||
"\n";
|
||||
}
|
||||
}
|
||||
if (getTools() != null) {
|
||||
for (ContributedTool tool : getTools())
|
||||
res += tool + "\n";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.contributions.packages;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ContributedPlatform extends DownloadableContribution {
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
public abstract String getCategory();
|
||||
|
||||
public abstract void setCategory(String category);
|
||||
|
||||
public abstract String getArchitecture();
|
||||
|
||||
public abstract String getChecksum();
|
||||
|
||||
public abstract List<ContributedToolReference> getToolsDependencies();
|
||||
|
||||
public abstract List<ContributedBoard> getBoards();
|
||||
|
||||
public abstract ContributedHelp getHelp();
|
||||
|
||||
private List<ContributedTool> resolvedTools = null;
|
||||
|
||||
private ContributedPackage parentPackage;
|
||||
|
||||
public List<ContributedTool> getResolvedTools() {
|
||||
if (resolvedTools == null) {
|
||||
return null;
|
||||
}
|
||||
return new LinkedList<ContributedTool>(resolvedTools);
|
||||
}
|
||||
|
||||
public void resolveToolsDependencies(Collection<ContributedPackage> packages) {
|
||||
resolvedTools = new ArrayList<ContributedTool>();
|
||||
|
||||
// If there are no dependencies return empty list
|
||||
if (getToolsDependencies() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// For each tool dependency
|
||||
for (ContributedToolReference dep : getToolsDependencies()) {
|
||||
// Search the referenced tool
|
||||
ContributedTool tool = dep.resolve(packages);
|
||||
if (tool == null) {
|
||||
System.err.println("Index error: could not find referenced tool " + dep);
|
||||
}
|
||||
resolvedTools.add(tool);
|
||||
}
|
||||
}
|
||||
|
||||
public ContributedPackage getParentPackage() {
|
||||
return parentPackage;
|
||||
}
|
||||
|
||||
public void setParentPackage(ContributedPackage parentPackage) {
|
||||
this.parentPackage = parentPackage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getParsedVersion();
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.contributions.packages;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import processing.app.debug.TargetPackage;
|
||||
import processing.app.debug.TargetPlatform;
|
||||
|
||||
public class ContributedTargetPackage implements TargetPackage {
|
||||
|
||||
private final String id;
|
||||
private final Map<String, TargetPlatform> platforms;
|
||||
|
||||
public ContributedTargetPackage(String _id) {
|
||||
id = _id;
|
||||
platforms = new HashMap<String, TargetPlatform>();
|
||||
}
|
||||
|
||||
void addPlatform(TargetPlatform p) {
|
||||
platforms.put(p.getId(), p);
|
||||
}
|
||||
|
||||
boolean hasPlatforms() {
|
||||
return platforms.size() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, TargetPlatform> getPlatforms() {
|
||||
return platforms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<TargetPlatform> platforms() {
|
||||
return platforms.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetPlatform get(String platform) {
|
||||
return platforms.get(platform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPlatform(TargetPlatform platform) {
|
||||
return platforms.containsKey(platform.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TargetPackage: " + getId();
|
||||
}
|
||||
}
|
@ -0,0 +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 cc.arduino.contributions.packages;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import processing.app.debug.LegacyTargetPlatform;
|
||||
import processing.app.debug.TargetPackage;
|
||||
import processing.app.debug.TargetPlatformException;
|
||||
|
||||
public class ContributedTargetPlatform extends LegacyTargetPlatform {
|
||||
|
||||
public ContributedTargetPlatform(String _name, File _folder,
|
||||
TargetPackage parent,
|
||||
ContributionsIndex index)
|
||||
throws TargetPlatformException {
|
||||
super(_name, _folder, parent);
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.contributions.packages;
|
||||
|
||||
import processing.app.BaseNoGui;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ContributedTool {
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
public abstract String getVersion();
|
||||
|
||||
public abstract List<HostDependentDownloadableContribution> getSystems();
|
||||
|
||||
public DownloadableContribution getDownloadableContribution() {
|
||||
for (HostDependentDownloadableContribution c : getSystems()) {
|
||||
if (c.isCompatible(BaseNoGui.getPlatform()))
|
||||
return c;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String res;
|
||||
res = "Tool name : " + getName() + " " + getVersion() + "\n";
|
||||
for (HostDependentDownloadableContribution sys : getSystems()) {
|
||||
res += " sys";
|
||||
res += sys.isCompatible(BaseNoGui.getPlatform()) ? "*" : " ";
|
||||
res += " : " + sys + "\n";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.contributions.packages;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public abstract class ContributedToolReference {
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
public abstract String getVersion();
|
||||
|
||||
public abstract String getPackager();
|
||||
|
||||
public ContributedTool resolve(Collection<ContributedPackage> packages) {
|
||||
for (ContributedPackage pack : packages) {
|
||||
for (ContributedTool tool : pack.getTools())
|
||||
if (tool.getName().equals(getName()) &&
|
||||
tool.getVersion().equals(getVersion()) &&
|
||||
pack.getName().equals(getPackager()))
|
||||
return tool;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "name=" + getName() + " version=" + getVersion() + " packager=" +
|
||||
getPackager();
|
||||
}
|
||||
}
|
@ -0,0 +1,302 @@
|
||||
/*
|
||||
* 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.contributions.packages;
|
||||
|
||||
import cc.arduino.contributions.GPGDetachedSignatureVerifier;
|
||||
import cc.arduino.filters.FileExecutablePredicate;
|
||||
import cc.arduino.utils.ArchiveExtractor;
|
||||
import cc.arduino.utils.MultiStepProgress;
|
||||
import cc.arduino.utils.Progress;
|
||||
import com.google.common.collect.Collections2;
|
||||
import org.apache.commons.exec.CommandLine;
|
||||
import org.apache.commons.exec.Executor;
|
||||
import processing.app.BaseNoGui;
|
||||
import processing.app.I18n;
|
||||
import processing.app.PreferencesData;
|
||||
import processing.app.helpers.FileUtils;
|
||||
import processing.app.helpers.filefilters.OnlyDirs;
|
||||
import processing.app.tools.CollectStdOutStdErrExecutor;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
import static processing.app.I18n.format;
|
||||
|
||||
public class ContributionInstaller {
|
||||
|
||||
private final ContributionsIndexer indexer;
|
||||
private final DownloadableContributionsDownloader downloader;
|
||||
|
||||
public ContributionInstaller(ContributionsIndexer contributionsIndexer) {
|
||||
File stagingFolder = contributionsIndexer.getStagingFolder();
|
||||
indexer = contributionsIndexer;
|
||||
downloader = new DownloadableContributionsDownloader(stagingFolder) {
|
||||
@Override
|
||||
protected void onProgress(Progress progress) {
|
||||
ContributionInstaller.this.onProgress(progress);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public List<String> install(ContributedPlatform platform) throws Exception {
|
||||
List<String> errors = new LinkedList<String>();
|
||||
if (platform.isInstalled()) {
|
||||
throw new Exception("Platform is already installed!");
|
||||
}
|
||||
|
||||
// Do not download already installed tools
|
||||
List<ContributedTool> tools = new LinkedList<ContributedTool>(platform.getResolvedTools());
|
||||
Iterator<ContributedTool> toolsIterator = tools.iterator();
|
||||
while (toolsIterator.hasNext()) {
|
||||
ContributedTool tool = toolsIterator.next();
|
||||
DownloadableContribution downloadable = tool.getDownloadableContribution();
|
||||
if (downloadable == null) {
|
||||
throw new Exception(format(_("Tool {0} is not available for your operating system."), tool.getName()));
|
||||
}
|
||||
if (downloadable.isInstalled()) {
|
||||
toolsIterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate progress increases
|
||||
MultiStepProgress progress = new MultiStepProgress((tools.size() + 1) * 2);
|
||||
|
||||
// Download all
|
||||
try {
|
||||
// Download platform
|
||||
downloader.download(platform, progress, _("Downloading boards definitions."));
|
||||
progress.stepDone();
|
||||
|
||||
// Download tools
|
||||
int i = 1;
|
||||
for (ContributedTool tool : tools) {
|
||||
String msg = format(_("Downloading tools ({0}/{1})."), i, tools.size());
|
||||
i++;
|
||||
downloader.download(tool.getDownloadableContribution(), progress, msg);
|
||||
progress.stepDone();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// Download interrupted... just exit
|
||||
return errors;
|
||||
}
|
||||
|
||||
ContributedPackage pack = platform.getParentPackage();
|
||||
File packageFolder = new File(indexer.getPackagesFolder(), pack.getName());
|
||||
|
||||
// TODO: Extract to temporary folders and move to the final destination only
|
||||
// once everything is successfully unpacked. If the operation fails remove
|
||||
// all the temporary folders and abort installation.
|
||||
|
||||
// Unzip tools on the correct location
|
||||
File toolsFolder = new File(packageFolder, "tools");
|
||||
int i = 1;
|
||||
for (ContributedTool tool : tools) {
|
||||
progress.setStatus(format(_("Installing tools ({0}/{1})..."), i, tools.size()));
|
||||
onProgress(progress);
|
||||
i++;
|
||||
DownloadableContribution toolContrib = tool.getDownloadableContribution();
|
||||
File destFolder = new File(toolsFolder, tool.getName() + File.separator + tool.getVersion());
|
||||
|
||||
destFolder.mkdirs();
|
||||
assert toolContrib.getDownloadedFile() != null;
|
||||
new ArchiveExtractor(BaseNoGui.getPlatform()).extract(toolContrib.getDownloadedFile(), destFolder, 1);
|
||||
try {
|
||||
executePostInstallScriptIfAny(destFolder);
|
||||
} catch (IOException e) {
|
||||
errors.add(_("Error running post install script"));
|
||||
}
|
||||
toolContrib.setInstalled(true);
|
||||
toolContrib.setInstalledFolder(destFolder);
|
||||
progress.stepDone();
|
||||
}
|
||||
|
||||
// Unpack platform on the correct location
|
||||
progress.setStatus(_("Installing boards..."));
|
||||
onProgress(progress);
|
||||
File platformFolder = new File(packageFolder, "hardware" + File.separator + platform.getArchitecture());
|
||||
File destFolder = new File(platformFolder, platform.getParsedVersion());
|
||||
destFolder.mkdirs();
|
||||
new ArchiveExtractor(BaseNoGui.getPlatform()).extract(platform.getDownloadedFile(), destFolder, 1);
|
||||
platform.setInstalled(true);
|
||||
platform.setInstalledFolder(destFolder);
|
||||
progress.stepDone();
|
||||
|
||||
progress.setStatus(_("Installation completed!"));
|
||||
onProgress(progress);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
private void executePostInstallScriptIfAny(File folder) throws IOException {
|
||||
Collection<File> postInstallScripts = Collections2.filter(BaseNoGui.getPlatform().postInstallScripts(folder), new FileExecutablePredicate());
|
||||
|
||||
if (postInstallScripts.isEmpty()) {
|
||||
String[] subfolders = folder.list(new OnlyDirs());
|
||||
if (subfolders.length != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
executePostInstallScriptIfAny(new File(folder, subfolders[0]));
|
||||
return;
|
||||
}
|
||||
|
||||
File postInstallScript = postInstallScripts.iterator().next();
|
||||
|
||||
ByteArrayOutputStream stdout = new ByteArrayOutputStream();
|
||||
ByteArrayOutputStream stderr = new ByteArrayOutputStream();
|
||||
Executor executor = new CollectStdOutStdErrExecutor(stdout, stderr);
|
||||
executor.setWorkingDirectory(folder);
|
||||
executor.setExitValues(null);
|
||||
int exitValue = executor.execute(new CommandLine(postInstallScript));
|
||||
executor.setExitValues(new int[0]);
|
||||
|
||||
System.out.write(stdout.toByteArray());
|
||||
System.err.write(stderr.toByteArray());
|
||||
|
||||
if (executor.isFailure(exitValue)) {
|
||||
throw new IOException();
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> remove(ContributedPlatform platform) {
|
||||
if (platform == null || platform.isReadOnly()) {
|
||||
return new LinkedList<String>();
|
||||
}
|
||||
List<String> errors = new LinkedList<String>();
|
||||
FileUtils.recursiveDelete(platform.getInstalledFolder());
|
||||
platform.setInstalled(false);
|
||||
platform.setInstalledFolder(null);
|
||||
|
||||
// Check if the tools are no longer needed
|
||||
for (ContributedTool tool : platform.getResolvedTools()) {
|
||||
if (indexer.isContributedToolUsed(tool)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DownloadableContribution toolContrib = tool.getDownloadableContribution();
|
||||
File destFolder = toolContrib.getInstalledFolder();
|
||||
FileUtils.recursiveDelete(destFolder);
|
||||
toolContrib.setInstalled(false);
|
||||
toolContrib.setInstalledFolder(null);
|
||||
|
||||
// We removed the version folder (.../tools/TOOL_NAME/VERSION)
|
||||
// now try to remove the containing TOOL_NAME folder
|
||||
// (and silently fail if another version of the tool is installed)
|
||||
try {
|
||||
destFolder.getParentFile().delete();
|
||||
} catch (SecurityException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
public List<String> updateIndex() throws Exception {
|
||||
MultiStepProgress progress = new MultiStepProgress(1);
|
||||
|
||||
List<String> downloadedPackageIndexFilesAccumulator = new LinkedList<String>();
|
||||
downloadIndexAndSignature(progress, downloadedPackageIndexFilesAccumulator, Constants.PACKAGE_INDEX_URL);
|
||||
|
||||
Set<String> packageIndexURLs = new HashSet<String>();
|
||||
String additionalURLs = PreferencesData.get(Constants.PREFERENCES_BOARDS_MANAGER_ADDITIONAL_URLS, "");
|
||||
if (!"".equals(additionalURLs)) {
|
||||
packageIndexURLs.addAll(Arrays.asList(additionalURLs.split(",")));
|
||||
}
|
||||
|
||||
for (String packageIndexURL : packageIndexURLs) {
|
||||
downloadIndexAndSignature(progress, downloadedPackageIndexFilesAccumulator, packageIndexURL);
|
||||
}
|
||||
|
||||
progress.stepDone();
|
||||
|
||||
return downloadedPackageIndexFilesAccumulator;
|
||||
}
|
||||
|
||||
private void downloadIndexAndSignature(MultiStepProgress progress, List<String> downloadedPackagedIndexFilesAccumulator, String packageIndexUrl) throws Exception {
|
||||
File packageIndex = download(progress, packageIndexUrl);
|
||||
downloadedPackagedIndexFilesAccumulator.add(packageIndex.getName());
|
||||
try {
|
||||
File packageIndexSignature = download(progress, packageIndexUrl + ".sig");
|
||||
boolean signatureVerified = new GPGDetachedSignatureVerifier().verify(packageIndex, packageIndexSignature, new File(BaseNoGui.getContentFile("lib"), "public.gpg.key"));
|
||||
if (signatureVerified) {
|
||||
downloadedPackagedIndexFilesAccumulator.add(packageIndexSignature.getName());
|
||||
} else {
|
||||
downloadedPackagedIndexFilesAccumulator.remove(packageIndex.getName());
|
||||
packageIndex.delete();
|
||||
packageIndexSignature.delete();
|
||||
System.err.println(I18n.format(_("{0} file signature verification failed. File ignored."), packageIndexUrl));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//ignore errors
|
||||
}
|
||||
}
|
||||
|
||||
private File download(MultiStepProgress progress, String packageIndexUrl) throws Exception {
|
||||
String statusText = _("Downloading platforms index...");
|
||||
URL url = new URL(packageIndexUrl);
|
||||
String[] urlPathParts = url.getFile().split("/");
|
||||
File outputFile = indexer.getIndexFile(urlPathParts[urlPathParts.length - 1]);
|
||||
File tmpFile = new File(outputFile.getAbsolutePath() + ".tmp");
|
||||
downloader.download(url, tmpFile, progress, statusText);
|
||||
|
||||
// Replace old index with the updated one
|
||||
if (outputFile.exists()) {
|
||||
if (!outputFile.delete()) {
|
||||
throw new Exception("An error occurred while updating platforms index! I can't delete file " + outputFile);
|
||||
}
|
||||
}
|
||||
if (!tmpFile.renameTo(outputFile)) {
|
||||
throw new Exception("An error occurred while updating platforms index! I can't rename file " + tmpFile);
|
||||
}
|
||||
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
protected void onProgress(Progress progress) {
|
||||
// Empty
|
||||
}
|
||||
|
||||
public void deleteUnknownFiles(List<String> downloadedPackageIndexFiles) {
|
||||
File preferencesFolder = indexer.getIndexFile(".").getParentFile();
|
||||
File[] additionalPackageIndexFiles = preferencesFolder.listFiles(new PackageIndexFilenameFilter(Constants.DEFAULT_INDEX_FILE_NAME));
|
||||
if (additionalPackageIndexFiles == null) {
|
||||
return;
|
||||
}
|
||||
for (File additionalPackageIndexFile : additionalPackageIndexFiles) {
|
||||
if (!downloadedPackageIndexFiles.contains(additionalPackageIndexFile.getName())) {
|
||||
additionalPackageIndexFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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.contributions.packages;
|
||||
|
||||
import cc.arduino.contributions.DownloadableContributionBuiltInAtTheBottomComparator;
|
||||
import cc.arduino.contributions.filters.DownloadableContributionWithVersionPredicate;
|
||||
import cc.arduino.contributions.filters.InstalledPredicate;
|
||||
import cc.arduino.contributions.packages.filters.PlatformArchitecturePredicate;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public abstract class ContributionsIndex {
|
||||
|
||||
public abstract List<ContributedPackage> getPackages();
|
||||
|
||||
public ContributedPackage findPackage(String packageName) {
|
||||
for (ContributedPackage pack : getPackages()) {
|
||||
if (pack.getName().equals(packageName))
|
||||
return pack;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<ContributedPlatform> findPlatforms(String packageName, final String platformArch) {
|
||||
if (packageName == null || platformArch == null) {
|
||||
return null;
|
||||
|
||||
}
|
||||
ContributedPackage aPackage = findPackage(packageName);
|
||||
if (aPackage == null) {
|
||||
return null;
|
||||
}
|
||||
Collection<ContributedPlatform> platforms = Collections2.filter(aPackage.getPlatforms(), new PlatformArchitecturePredicate(platformArch));
|
||||
return Lists.newLinkedList(platforms);
|
||||
}
|
||||
|
||||
public ContributedPlatform findPlatform(String packageName, final String platformArch, final String platformVersion) {
|
||||
if (platformVersion == null) {
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
Collection<ContributedPlatform> platformsByName = findPlatforms(packageName, platformArch);
|
||||
if (platformsByName == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Collection<ContributedPlatform> platforms = Collections2.filter(platformsByName, new DownloadableContributionWithVersionPredicate(platformVersion));
|
||||
if (platforms.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return platforms.iterator().next();
|
||||
}
|
||||
|
||||
public ContributedPlatform getInstalled(String packageName, String platformArch) {
|
||||
List<ContributedPlatform> installedPlatforms = new LinkedList<ContributedPlatform>(Collections2.filter(findPlatforms(packageName, platformArch), new InstalledPredicate()));
|
||||
Collections.sort(installedPlatforms, new DownloadableContributionBuiltInAtTheBottomComparator());
|
||||
|
||||
if (installedPlatforms.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return installedPlatforms.get(0);
|
||||
}
|
||||
|
||||
public List<ContributedPlatform> getPlatforms() {
|
||||
return Lists.newLinkedList(Iterables.concat(Collections2.transform(getPackages(), new Function<ContributedPackage, List<ContributedPlatform>>() {
|
||||
@Override
|
||||
public List<ContributedPlatform> apply(ContributedPackage contributedPackage) {
|
||||
return contributedPackage.getPlatforms();
|
||||
}
|
||||
})));
|
||||
}
|
||||
|
||||
|
||||
public ContributedTool findTool(String packageName, String name,
|
||||
String version) {
|
||||
ContributedPackage pack = findPackage(packageName);
|
||||
if (pack == null)
|
||||
return null;
|
||||
return pack.findTool(name, version);
|
||||
}
|
||||
|
||||
private final List<String> categories = new ArrayList<String>();
|
||||
|
||||
public List<String> getCategories() {
|
||||
return categories;
|
||||
}
|
||||
|
||||
public void fillCategories() {
|
||||
categories.clear();
|
||||
for (ContributedPackage pack : getPackages()) {
|
||||
for (ContributedPlatform platform : pack.getPlatforms()) {
|
||||
if (!categories.contains(platform.getCategory()))
|
||||
categories.add(platform.getCategory());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ContributedPackage getPackage(String packageName) {
|
||||
for (ContributedPackage pack : getPackages()) {
|
||||
if (pack.getName().equals(packageName)) {
|
||||
return pack;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String res = "";
|
||||
res += "Categories: ";
|
||||
for (String c : getCategories())
|
||||
res += "'" + c + "' ";
|
||||
res += "\n";
|
||||
for (ContributedPackage pack : getPackages())
|
||||
res += pack + "\n";
|
||||
return res;
|
||||
}
|
||||
}
|
@ -0,0 +1,403 @@
|
||||
/*
|
||||
* 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.contributions.packages;
|
||||
|
||||
import cc.arduino.contributions.DownloadableContributionBuiltInAtTheBottomComparator;
|
||||
import cc.arduino.contributions.GPGDetachedSignatureVerifier;
|
||||
import cc.arduino.contributions.SignatureVerificationFailedException;
|
||||
import cc.arduino.contributions.filters.BuiltInPredicate;
|
||||
import cc.arduino.contributions.filters.InstalledPredicate;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.module.mrbean.MrBeanModule;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import processing.app.BaseNoGui;
|
||||
import processing.app.debug.TargetPackage;
|
||||
import processing.app.debug.TargetPlatform;
|
||||
import processing.app.debug.TargetPlatformException;
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
|
||||
import static processing.app.helpers.filefilters.OnlyDirs.ONLY_DIRS;
|
||||
|
||||
public class ContributionsIndexer {
|
||||
|
||||
private final File packagesFolder;
|
||||
private final File stagingFolder;
|
||||
private final File preferencesFolder;
|
||||
private ContributionsIndex index;
|
||||
|
||||
public ContributionsIndexer(File preferencesFolder) {
|
||||
this.preferencesFolder = preferencesFolder;
|
||||
packagesFolder = new File(preferencesFolder, "packages");
|
||||
stagingFolder = new File(preferencesFolder, "staging" + File.separator + "packages");
|
||||
}
|
||||
|
||||
public void parseIndex() throws Exception {
|
||||
File defaultIndexFile = getIndexFile(Constants.DEFAULT_INDEX_FILE_NAME);
|
||||
if (!isSigned(defaultIndexFile)) {
|
||||
throw new SignatureVerificationFailedException(Constants.DEFAULT_INDEX_FILE_NAME);
|
||||
}
|
||||
index = parseIndex(defaultIndexFile);
|
||||
|
||||
File[] indexFiles = preferencesFolder.listFiles(new TestPackageIndexFilenameFilter(new PackageIndexFilenameFilter(Constants.DEFAULT_INDEX_FILE_NAME)));
|
||||
|
||||
for (File indexFile : indexFiles) {
|
||||
ContributionsIndex contributionsIndex = parseIndex(indexFile);
|
||||
mergeContributions(contributionsIndex, indexFile);
|
||||
}
|
||||
|
||||
List<ContributedPackage> packages = index.getPackages();
|
||||
for (ContributedPackage pack : packages) {
|
||||
for (ContributedPlatform platform : pack.getPlatforms()) {
|
||||
// Set a reference to parent packages
|
||||
platform.setParentPackage(pack);
|
||||
|
||||
// Resolve tools dependencies (works also as a check for file integrity)
|
||||
platform.resolveToolsDependencies(packages);
|
||||
}
|
||||
}
|
||||
|
||||
index.fillCategories();
|
||||
}
|
||||
|
||||
private void mergeContributions(ContributionsIndex contributionsIndex, File indexFile) {
|
||||
boolean signed = isSigned(indexFile);
|
||||
|
||||
for (ContributedPackage contributedPackage : contributionsIndex.getPackages()) {
|
||||
if (!signed) {
|
||||
for (ContributedPlatform contributedPlatform : contributedPackage.getPlatforms()) {
|
||||
contributedPlatform.setCategory("Contributed");
|
||||
}
|
||||
}
|
||||
|
||||
ContributedPackage targetPackage = index.getPackage(contributedPackage.getName());
|
||||
|
||||
if (targetPackage == null) {
|
||||
index.getPackages().add(contributedPackage);
|
||||
} else {
|
||||
if (signed || !isPackageNameProtected(contributedPackage)) {
|
||||
List<ContributedPlatform> platforms = contributedPackage.getPlatforms();
|
||||
if (platforms == null) {
|
||||
platforms = new LinkedList<ContributedPlatform>();
|
||||
}
|
||||
for (ContributedPlatform contributedPlatform : platforms) {
|
||||
ContributedPlatform platform = targetPackage.findPlatform(contributedPlatform.getArchitecture(), contributedPlatform.getVersion());
|
||||
if (platform != null) {
|
||||
targetPackage.getPlatforms().remove(platform);
|
||||
}
|
||||
targetPackage.getPlatforms().add(contributedPlatform);
|
||||
}
|
||||
List<ContributedTool> tools = contributedPackage.getTools();
|
||||
if (tools == null) {
|
||||
tools = new LinkedList<ContributedTool>();
|
||||
}
|
||||
for (ContributedTool contributedTool : tools) {
|
||||
ContributedTool tool = targetPackage.findTool(contributedTool.getName(), contributedTool.getVersion());
|
||||
if (tool != null) {
|
||||
targetPackage.getTools().remove(tool);
|
||||
}
|
||||
targetPackage.getTools().add(contributedTool);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPackageNameProtected(ContributedPackage contributedPackage) {
|
||||
return Constants.PROTECTED_PACKAGE_NAMES.contains(contributedPackage.getName());
|
||||
}
|
||||
|
||||
private boolean isSigned(File indexFile) {
|
||||
File signature = new File(indexFile.getParent(), indexFile.getName() + ".sig");
|
||||
if (!signature.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return new GPGDetachedSignatureVerifier().verify(indexFile, signature, new File(BaseNoGui.getContentFile("lib"), "public.gpg.key"));
|
||||
} catch (Exception e) {
|
||||
BaseNoGui.showWarning(e.getMessage(), e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private ContributionsIndex parseIndex(File indexFile) throws IOException {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = 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, false);
|
||||
return mapper.readValue(inputStream, ContributionsIndex.class);
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void syncWithFilesystem(File hardwareFolder) throws IOException {
|
||||
syncBuiltInHardwareFolder(hardwareFolder);
|
||||
|
||||
syncLocalPackagesFolder();
|
||||
}
|
||||
|
||||
public void syncBuiltInHardwareFolder(File hardwareFolder) throws IOException {
|
||||
if (index == null) {
|
||||
return;
|
||||
}
|
||||
for (File folder : hardwareFolder.listFiles(ONLY_DIRS)) {
|
||||
ContributedPackage pack = index.findPackage(folder.getName());
|
||||
if (pack != null) {
|
||||
syncBuiltInPackageWithFilesystem(pack, folder);
|
||||
|
||||
File toolsFolder = new File(hardwareFolder, "tools");
|
||||
if (toolsFolder.isDirectory()) {
|
||||
for (File toolFolder : toolsFolder.listFiles(ONLY_DIRS)) {
|
||||
File builtInToolsMetadata = new File(toolFolder, "builtin_tools_versions.txt");
|
||||
if (builtInToolsMetadata.isFile()) {
|
||||
PreferencesMap toolsMetadata = new PreferencesMap(builtInToolsMetadata).subTree(pack.getName());
|
||||
for (Map.Entry<String, String> toolMetadata : toolsMetadata.entrySet()) {
|
||||
syncToolWithFilesystem(pack, toolFolder, toolMetadata.getKey(), toolMetadata.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void syncBuiltInPackageWithFilesystem(ContributedPackage pack, File hardwareFolder) throws IOException {
|
||||
// Scan all hardware folders and mark as installed all the tools found.
|
||||
for (File platformFolder : hardwareFolder.listFiles(ONLY_DIRS)) {
|
||||
File platformTxt = new File(platformFolder, "platform.txt");
|
||||
String version = new PreferencesMap(platformTxt).get("version");
|
||||
ContributedPlatform platform = syncHardwareWithFilesystem(pack, platformFolder, platformFolder.getName(), version);
|
||||
if (platform != null) {
|
||||
platform.setReadOnly(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void syncLocalPackagesFolder() {
|
||||
if (!packagesFolder.isDirectory()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scan all hardware folders and mark as installed all the
|
||||
// platforms found.
|
||||
for (File folder : packagesFolder.listFiles(ONLY_DIRS)) {
|
||||
ContributedPackage pack = index.findPackage(folder.getName());
|
||||
if (pack != null) {
|
||||
syncPackageWithFilesystem(pack, folder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void syncPackageWithFilesystem(ContributedPackage pack, File root) {
|
||||
// Scan all hardware folders and mark as installed all the tools found.
|
||||
File hardwareFolder = new File(root, "hardware");
|
||||
if (hardwareFolder.isDirectory()) {
|
||||
for (File platformFolder : hardwareFolder.listFiles(ONLY_DIRS)) {
|
||||
for (File versionFolder : platformFolder.listFiles(ONLY_DIRS)) {
|
||||
syncHardwareWithFilesystem(pack, versionFolder, platformFolder.getName(), versionFolder.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scan all tools folders and mark as installed all the tools found.
|
||||
File toolsFolder = new File(root, "tools");
|
||||
if (toolsFolder.isDirectory()) {
|
||||
for (File toolFolder : toolsFolder.listFiles(ONLY_DIRS)) {
|
||||
for (File versionFolder : toolFolder.listFiles(ONLY_DIRS)) {
|
||||
syncToolWithFilesystem(pack, versionFolder, toolFolder.getName(), versionFolder.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void syncToolWithFilesystem(ContributedPackage pack, File installationFolder, String toolName, String version) {
|
||||
ContributedTool tool = pack.findTool(toolName, version);
|
||||
if (tool == null) {
|
||||
return;
|
||||
}
|
||||
DownloadableContribution contrib = tool.getDownloadableContribution();
|
||||
if (contrib == null) {
|
||||
System.err.println(tool + " seems to have no downloadable contributions for your operating system, but it is installed in\n" + installationFolder);
|
||||
return;
|
||||
}
|
||||
contrib.setInstalled(true);
|
||||
contrib.setInstalledFolder(installationFolder);
|
||||
}
|
||||
|
||||
private ContributedPlatform syncHardwareWithFilesystem(ContributedPackage pack, File installationFolder, String architecture, String version) {
|
||||
ContributedPlatform platform = pack.findPlatform(architecture, version);
|
||||
if (platform != null) {
|
||||
platform.setInstalled(true);
|
||||
platform.setReadOnly(false);
|
||||
platform.setInstalledFolder(installationFolder);
|
||||
}
|
||||
return platform;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return index.toString();
|
||||
}
|
||||
|
||||
public List<TargetPackage> createTargetPackages() throws TargetPlatformException {
|
||||
List<TargetPackage> packages = new ArrayList<TargetPackage>();
|
||||
|
||||
if (index == null) {
|
||||
return packages;
|
||||
}
|
||||
|
||||
for (ContributedPackage aPackage : index.getPackages()) {
|
||||
ContributedTargetPackage targetPackage = new ContributedTargetPackage(aPackage.getName());
|
||||
|
||||
List<ContributedPlatform> platforms = new LinkedList<ContributedPlatform>(Collections2.filter(aPackage.getPlatforms(), new InstalledPredicate()));
|
||||
Collections.sort(platforms, new DownloadableContributionBuiltInAtTheBottomComparator());
|
||||
|
||||
for (ContributedPlatform platform : platforms) {
|
||||
String arch = platform.getArchitecture();
|
||||
File folder = platform.getInstalledFolder();
|
||||
|
||||
TargetPlatform targetPlatform = new ContributedTargetPlatform(arch, folder, targetPackage, index);
|
||||
if (!targetPackage.hasPlatform(targetPlatform)) {
|
||||
targetPackage.addPlatform(targetPlatform);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPackage.hasPlatforms()) {
|
||||
packages.add(targetPackage);
|
||||
}
|
||||
}
|
||||
return packages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a ContributedTool is currently in use by an installed platform
|
||||
*
|
||||
* @param tool
|
||||
* @return
|
||||
*/
|
||||
public boolean isContributedToolUsed(ContributedTool tool) {
|
||||
for (ContributedPackage pack : index.getPackages()) {
|
||||
for (ContributedPlatform platform : pack.getPlatforms()) {
|
||||
if (!platform.isInstalled())
|
||||
continue;
|
||||
for (ContributedTool requiredTool : platform.getResolvedTools()) {
|
||||
if (requiredTool.equals(tool))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Set<ContributedTool> getInstalledTools() {
|
||||
Set<ContributedTool> tools = new HashSet<ContributedTool>();
|
||||
if (index == null) {
|
||||
return tools;
|
||||
}
|
||||
for (ContributedPackage pack : index.getPackages()) {
|
||||
Collection<ContributedPlatform> platforms = Collections2.filter(pack.getPlatforms(), new InstalledPredicate());
|
||||
ImmutableListMultimap<String, ContributedPlatform> platformsByName = Multimaps.index(platforms, new Function<ContributedPlatform, String>() {
|
||||
@Override
|
||||
public String apply(ContributedPlatform contributedPlatform) {
|
||||
return contributedPlatform.getName();
|
||||
}
|
||||
});
|
||||
|
||||
for (Map.Entry<String, Collection<ContributedPlatform>> entry : platformsByName.asMap().entrySet()) {
|
||||
Collection<ContributedPlatform> platformsWithName = entry.getValue();
|
||||
if (platformsWithName.size() > 1) {
|
||||
platformsWithName = Collections2.filter(platformsWithName, Predicates.not(new BuiltInPredicate()));
|
||||
}
|
||||
for (ContributedPlatform platform : platformsWithName) {
|
||||
tools.addAll(platform.getResolvedTools());
|
||||
}
|
||||
}
|
||||
}
|
||||
return tools;
|
||||
}
|
||||
|
||||
public ContributionsIndex getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public File getPackagesFolder() {
|
||||
return packagesFolder;
|
||||
}
|
||||
|
||||
public File getStagingFolder() {
|
||||
return stagingFolder;
|
||||
}
|
||||
|
||||
public File getIndexFile(String name) {
|
||||
return new File(preferencesFolder, name);
|
||||
}
|
||||
|
||||
public List<ContributedPackage> getPackages() {
|
||||
if (index == null) {
|
||||
return new LinkedList<ContributedPackage>();
|
||||
}
|
||||
return index.getPackages();
|
||||
}
|
||||
|
||||
public List<String> getCategories() {
|
||||
if (index == null) {
|
||||
return new LinkedList<String>();
|
||||
}
|
||||
return index.getCategories();
|
||||
}
|
||||
|
||||
public ContributedPlatform getInstalled(String packageName, String platformArch) {
|
||||
if (index == null) {
|
||||
return null;
|
||||
}
|
||||
return index.getInstalled(packageName, platformArch);
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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.contributions.packages;
|
||||
|
||||
import cc.arduino.contributions.VersionHelper;
|
||||
import com.github.zafarkhaja.semver.Version;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public abstract class DownloadableContribution {
|
||||
|
||||
private boolean installed;
|
||||
private File installedFolder;
|
||||
|
||||
private boolean downloaded;
|
||||
private File downloadedFile;
|
||||
|
||||
public abstract String getUrl();
|
||||
|
||||
public abstract String getVersion();
|
||||
|
||||
public abstract String getChecksum();
|
||||
|
||||
public abstract long getSize();
|
||||
|
||||
public abstract String getArchiveFileName();
|
||||
|
||||
public boolean isDownloaded() {
|
||||
return downloaded;
|
||||
}
|
||||
|
||||
public void setDownloaded(boolean downloaded) {
|
||||
this.downloaded = downloaded;
|
||||
}
|
||||
|
||||
public File getDownloadedFile() {
|
||||
return downloadedFile;
|
||||
}
|
||||
|
||||
public void setDownloadedFile(File downloadedFile) {
|
||||
this.downloadedFile = downloadedFile;
|
||||
}
|
||||
|
||||
public boolean isInstalled() {
|
||||
return installed;
|
||||
}
|
||||
|
||||
public void setInstalled(boolean installed) {
|
||||
this.installed = installed;
|
||||
}
|
||||
|
||||
public File getInstalledFolder() {
|
||||
return installedFolder;
|
||||
}
|
||||
|
||||
public void setInstalledFolder(File installedFolder) {
|
||||
this.installedFolder = installedFolder;
|
||||
}
|
||||
|
||||
private boolean readOnly;
|
||||
|
||||
public boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
|
||||
public String getParsedVersion() {
|
||||
Version version = VersionHelper.valueOf(getVersion());
|
||||
if (version == null) {
|
||||
return null;
|
||||
}
|
||||
return version.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String res = "";
|
||||
if (installed) {
|
||||
res += "installed on " + installedFolder.getAbsolutePath() + " (" + getSize() + " bytes)";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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.contributions.packages;
|
||||
|
||||
import cc.arduino.utils.FileHash;
|
||||
import cc.arduino.utils.Progress;
|
||||
import cc.arduino.utils.network.FileDownloader;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
import static processing.app.I18n.format;
|
||||
|
||||
public class DownloadableContributionsDownloader {
|
||||
|
||||
private final File stagingFolder;
|
||||
|
||||
public DownloadableContributionsDownloader(File _stagingFolder) {
|
||||
stagingFolder = _stagingFolder;
|
||||
}
|
||||
|
||||
public File download(DownloadableContribution contribution,
|
||||
final Progress progress, final String statusText)
|
||||
throws Exception {
|
||||
URL url = new URL(contribution.getUrl());
|
||||
final File outputFile = new File(stagingFolder, contribution.getArchiveFileName());
|
||||
|
||||
// Ensure the existence of staging folder
|
||||
stagingFolder.mkdirs();
|
||||
|
||||
// Need to download or resume downloading?
|
||||
if (!outputFile.isFile() || (outputFile.length() < contribution.getSize())) {
|
||||
download(url, outputFile, progress, statusText);
|
||||
}
|
||||
|
||||
// Test checksum
|
||||
progress.setStatus(_("Verifying archive integrity..."));
|
||||
onProgress(progress);
|
||||
String checksum = contribution.getChecksum();
|
||||
String algo = checksum.split(":")[0];
|
||||
if (!FileHash.hash(outputFile, algo).equalsIgnoreCase(checksum)) {
|
||||
throw new Exception(_("CRC doesn't match. File is corrupted."));
|
||||
}
|
||||
|
||||
contribution.setDownloaded(true);
|
||||
contribution.setDownloadedFile(outputFile);
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
public void download(URL url, File tmpFile, final Progress progress,
|
||||
final String statusText) throws Exception {
|
||||
FileDownloader downloader = new FileDownloader(url, tmpFile);
|
||||
downloader.addObserver(new Observer() {
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
FileDownloader me = (FileDownloader) o;
|
||||
String msg = "";
|
||||
if (me.getDownloadSize() != null) {
|
||||
long downloaded = (me.getInitialSize() + me.getDownloaded()) / 1000;
|
||||
long total = (me.getInitialSize() + me.getDownloadSize()) / 1000;
|
||||
msg = format(_("Downloaded {0}kb of {1}kb."), downloaded, total);
|
||||
}
|
||||
progress.setStatus(statusText + " " + msg);
|
||||
progress.setProgress(me.getProgress());
|
||||
onProgress(progress);
|
||||
}
|
||||
});
|
||||
downloader.download();
|
||||
if (!downloader.isCompleted()) {
|
||||
throw new Exception(format(_("Error downloading {0}"), url), downloader.getError());
|
||||
}
|
||||
}
|
||||
|
||||
protected void onProgress(Progress progress) {
|
||||
// Empty
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.contributions.packages;
|
||||
|
||||
import processing.app.Platform;
|
||||
|
||||
public abstract class HostDependentDownloadableContribution extends DownloadableContribution {
|
||||
|
||||
public abstract String getHost();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getHost() + " " + super.toString();
|
||||
}
|
||||
|
||||
public boolean isCompatible(Platform platform) {
|
||||
String osName = platform.getOsName();
|
||||
assert osName != null;
|
||||
String osArch = platform.getOsArch();
|
||||
assert osArch != null;
|
||||
|
||||
String host = getHost();
|
||||
|
||||
if (osName.contains("Linux")) {
|
||||
if (osArch.contains("amd64")) {
|
||||
return host.matches("x86_64-.*linux-gnu");
|
||||
} else {
|
||||
return host.matches("i[3456]86-.*linux-gnu");
|
||||
}
|
||||
}
|
||||
|
||||
if (osName.contains("Windows")) {
|
||||
return host.matches("i[3456]86-.*mingw32") || host.matches("i[3456]86-.*cygwin");
|
||||
}
|
||||
|
||||
if (osName.contains("Mac")) {
|
||||
if (osArch.contains("x86_64")) {
|
||||
return host.matches("x86_64-apple-darwin.*") || host.matches("i[3456]86-apple-darwin.*");
|
||||
} else {
|
||||
return host.matches("i[3456]86-apple-darwin.*");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package cc.arduino.contributions.packages;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
|
||||
public class PackageIndexFilenameFilter implements FilenameFilter {
|
||||
|
||||
private final String defaultPackageIndexFileName;
|
||||
|
||||
public PackageIndexFilenameFilter(String defaultPackageIndexFileName) {
|
||||
this.defaultPackageIndexFileName = defaultPackageIndexFileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(File file, String name) {
|
||||
return new File(file, name).isFile() && !defaultPackageIndexFileName.equals(name) && name.startsWith("package_") && name.endsWith("_index.json");
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package cc.arduino.contributions.packages;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
|
||||
public class TestPackageIndexFilenameFilter implements FilenameFilter {
|
||||
|
||||
private final FilenameFilter parent;
|
||||
|
||||
public TestPackageIndexFilenameFilter(FilenameFilter parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public TestPackageIndexFilenameFilter() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(File file, String name) {
|
||||
boolean result = false;
|
||||
if (parent != null) {
|
||||
result = parent.accept(file, name);
|
||||
}
|
||||
result = result || (new File(file, name).isFile() && name.startsWith("test_package_") && name.endsWith("_index.json"));
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* Copyright 2015 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.contributions.packages.filters;
|
||||
|
||||
import cc.arduino.contributions.packages.ContributedPlatform;
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
public class PlatformArchitecturePredicate implements Predicate<ContributedPlatform> {
|
||||
|
||||
private final String platformArch;
|
||||
|
||||
public PlatformArchitecturePredicate(String platformArch) {
|
||||
this.platformArch = platformArch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(ContributedPlatform contributedPlatform) {
|
||||
return platformArch.equals(contributedPlatform.getArchitecture());
|
||||
}
|
||||
|
||||
}
|
47
arduino-core/src/cc/arduino/files/DeleteFilesOnShutdown.java
Normal file
47
arduino-core/src/cc/arduino/files/DeleteFilesOnShutdown.java
Normal file
@ -0,0 +1,47 @@
|
||||
package cc.arduino.files;
|
||||
|
||||
import processing.app.PreferencesData;
|
||||
import processing.app.helpers.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class DeleteFilesOnShutdown implements Runnable {
|
||||
|
||||
public static final DeleteFilesOnShutdown INSTANCE = new DeleteFilesOnShutdown();
|
||||
|
||||
public static void add(File file) {
|
||||
INSTANCE.addFile(file);
|
||||
}
|
||||
|
||||
private final List<File> files;
|
||||
|
||||
public DeleteFilesOnShutdown() {
|
||||
this.files = new LinkedList<File>();
|
||||
}
|
||||
|
||||
public synchronized void addFile(File file) {
|
||||
this.files.add(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
boolean preserveTempFiles = PreferencesData.getBoolean("runtime.preserve.temp.files");
|
||||
if (preserveTempFiles) {
|
||||
return;
|
||||
}
|
||||
List<File> copyOfFiles;
|
||||
synchronized (this) {
|
||||
copyOfFiles = new LinkedList<File>(files);
|
||||
}
|
||||
Collections.reverse(copyOfFiles);
|
||||
for (File file : copyOfFiles) {
|
||||
if (file.exists() && file.canWrite()) {
|
||||
FileUtils.recursiveDelete(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* Copyright 2015 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.filters;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class FileExecutablePredicate implements Predicate<File> {
|
||||
|
||||
@Override
|
||||
public boolean apply(File file) {
|
||||
return file.isFile() && file.exists() && file.canRead() && file.canExecute();
|
||||
}
|
||||
|
||||
}
|
@ -29,36 +29,27 @@
|
||||
|
||||
package cc.arduino.packages;
|
||||
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface Discovery {
|
||||
|
||||
/**
|
||||
* Set discovery preferences
|
||||
*
|
||||
* @param options
|
||||
*/
|
||||
public void setPreferences(PreferencesMap options);
|
||||
|
||||
/**
|
||||
* Start discovery service
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void start() throws Exception;
|
||||
void start() throws Exception;
|
||||
|
||||
/**
|
||||
* Stop discovery service
|
||||
*/
|
||||
public void stop() throws Exception;
|
||||
void stop() throws Exception;
|
||||
|
||||
/**
|
||||
* Return the list of discovered ports.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<BoardPort> discovery();
|
||||
List<BoardPort> listDiscoveredBoards();
|
||||
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ public class DiscoveryManager {
|
||||
try {
|
||||
d.stop();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||
e.printStackTrace(); //just printing as the JVM is terminating
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -74,7 +74,7 @@ public class DiscoveryManager {
|
||||
public List<BoardPort> discovery() {
|
||||
List<BoardPort> res = new ArrayList<BoardPort>();
|
||||
for (Discovery d : discoverers) {
|
||||
res.addAll(d.discovery());
|
||||
res.addAll(d.listDiscoveredBoards());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -36,8 +36,9 @@ import processing.app.debug.TargetBoard;
|
||||
public class UploaderFactory {
|
||||
|
||||
public Uploader newUploader(TargetBoard board, BoardPort port, boolean noUploadPort) {
|
||||
if (noUploadPort)
|
||||
return new SerialUploader(noUploadPort);
|
||||
if (noUploadPort) {
|
||||
return new SerialUploader(true);
|
||||
}
|
||||
|
||||
if ("true".equals(board.getPreferences().get("upload.via_ssh")) && port != null && "network".equals(port.getProtocol())) {
|
||||
return new SSHUploader(port);
|
||||
|
@ -31,9 +31,9 @@ package cc.arduino.packages.discoverers;
|
||||
|
||||
import cc.arduino.packages.BoardPort;
|
||||
import cc.arduino.packages.Discovery;
|
||||
import cc.arduino.packages.discoverers.network.BoardReachabilityFilter;
|
||||
import cc.arduino.packages.discoverers.network.NetworkChecker;
|
||||
import processing.app.BaseNoGui;
|
||||
import processing.app.helpers.NetUtils;
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
import processing.app.zeroconf.jmdns.ArduinoDNSTaskStarter;
|
||||
|
||||
@ -41,70 +41,57 @@ import javax.jmdns.*;
|
||||
import javax.jmdns.impl.DNSTaskStarter;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.*;
|
||||
|
||||
public class NetworkDiscovery implements Discovery, ServiceListener, cc.arduino.packages.discoverers.network.NetworkTopologyListener {
|
||||
|
||||
private Timer timer;
|
||||
private final List<BoardPort> ports;
|
||||
private static final int MAX_TIME_AWAITING_FOR_PACKAGES = 5000;
|
||||
|
||||
private final List<BoardPort> boardPortsDiscoveredWithJmDNS;
|
||||
private final Map<InetAddress, JmDNS> mappedJmDNSs;
|
||||
private Timer networkCheckerTimer;
|
||||
private Timer boardReachabilityFilterTimer;
|
||||
private final List<BoardPort> reachableBoardPorts;
|
||||
|
||||
public NetworkDiscovery() {
|
||||
DNSTaskStarter.Factory.setClassDelegate(new ArduinoDNSTaskStarter());
|
||||
this.ports = new ArrayList<BoardPort>();
|
||||
this.boardPortsDiscoveredWithJmDNS = new LinkedList<BoardPort>();
|
||||
this.mappedJmDNSs = new Hashtable<InetAddress, JmDNS>();
|
||||
this.reachableBoardPorts = new LinkedList<BoardPort>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BoardPort> discovery() {
|
||||
List<BoardPort> boardPorts = clonePortsList();
|
||||
Iterator<BoardPort> boardPortIterator = boardPorts.iterator();
|
||||
while (boardPortIterator.hasNext()) {
|
||||
try {
|
||||
BoardPort board = boardPortIterator.next();
|
||||
|
||||
InetAddress inetAddress = InetAddress.getByName(board.getAddress());
|
||||
int broadcastedPort = Integer.valueOf(board.getPrefs().get("port"));
|
||||
|
||||
List<Integer> ports = new LinkedList<Integer>();
|
||||
ports.add(broadcastedPort);
|
||||
|
||||
//dirty code: allows non up to date yuns to be discovered. Newer yuns will broadcast port 22
|
||||
if (broadcastedPort == 80) {
|
||||
ports.add(0, 22);
|
||||
}
|
||||
|
||||
boolean reachable = NetUtils.isReachable(inetAddress, ports);
|
||||
if (!reachable) {
|
||||
boardPortIterator.remove();
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
boardPortIterator.remove();
|
||||
}
|
||||
}
|
||||
return boardPorts;
|
||||
}
|
||||
|
||||
private List<BoardPort> clonePortsList() {
|
||||
synchronized (this) {
|
||||
return new ArrayList<BoardPort>(this.ports);
|
||||
public List<BoardPort> listDiscoveredBoards() {
|
||||
synchronized (reachableBoardPorts) {
|
||||
return new LinkedList<BoardPort>(reachableBoardPorts);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPreferences(PreferencesMap options) {
|
||||
public void setReachableBoardPorts(List<BoardPort> newReachableBoardPorts) {
|
||||
synchronized (reachableBoardPorts) {
|
||||
this.reachableBoardPorts.clear();
|
||||
this.reachableBoardPorts.addAll(newReachableBoardPorts);
|
||||
}
|
||||
}
|
||||
|
||||
public List<BoardPort> getBoardPortsDiscoveredWithJmDNS() {
|
||||
synchronized (boardPortsDiscoveredWithJmDNS) {
|
||||
return new LinkedList<BoardPort>(boardPortsDiscoveredWithJmDNS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() throws IOException {
|
||||
this.timer = new Timer(this.getClass().getName() + " timer");
|
||||
new NetworkChecker(this, NetworkTopologyDiscovery.Factory.getInstance()).start(timer);
|
||||
this.networkCheckerTimer = new Timer(NetworkChecker.class.getName());
|
||||
new NetworkChecker(this, NetworkTopologyDiscovery.Factory.getInstance()).start(networkCheckerTimer);
|
||||
this.boardReachabilityFilterTimer = new Timer(BoardReachabilityFilter.class.getName());
|
||||
new BoardReachabilityFilter(this).start(boardReachabilityFilterTimer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() throws IOException {
|
||||
timer.purge();
|
||||
this.networkCheckerTimer.purge();
|
||||
this.boardReachabilityFilterTimer.purge();
|
||||
// we don't close each JmDNS instance as it's too slow
|
||||
}
|
||||
|
||||
@ -125,16 +112,27 @@ public class NetworkDiscovery implements Discovery, ServiceListener, cc.arduino.
|
||||
@Override
|
||||
public void serviceRemoved(ServiceEvent serviceEvent) {
|
||||
String name = serviceEvent.getName();
|
||||
synchronized (this) {
|
||||
for (BoardPort port : ports) {
|
||||
if (port.getBoardName().equals(name))
|
||||
ports.remove(port);
|
||||
synchronized (boardPortsDiscoveredWithJmDNS) {
|
||||
for (BoardPort port : boardPortsDiscoveredWithJmDNS) {
|
||||
if (port.getBoardName().equals(name)) {
|
||||
boardPortsDiscoveredWithJmDNS.remove(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceResolved(ServiceEvent serviceEvent) {
|
||||
int sleptFor = 0;
|
||||
while (BaseNoGui.packages == null && sleptFor <= MAX_TIME_AWAITING_FOR_PACKAGES) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
sleptFor += 1000;
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
ServiceInfo info = serviceEvent.getInfo();
|
||||
for (InetAddress inetAddress : info.getInet4Addresses()) {
|
||||
String address = inetAddress.getHostAddress();
|
||||
@ -147,12 +145,11 @@ public class NetworkDiscovery implements Discovery, ServiceListener, cc.arduino.
|
||||
board = info.getPropertyString("board");
|
||||
prefs.put("board", board);
|
||||
prefs.put("distro_version", info.getPropertyString("distro_version"));
|
||||
prefs.put("port", "" + info.getPort());
|
||||
}
|
||||
|
||||
prefs.put("port", "" + info.getPort());
|
||||
|
||||
String label = name + " at " + address;
|
||||
if (board != null) {
|
||||
if (board != null && BaseNoGui.packages != null) {
|
||||
String boardName = BaseNoGui.getPlatform().resolveDeviceByBoardID(BaseNoGui.packages, board);
|
||||
if (boardName != null) {
|
||||
label += " (" + boardName + ")";
|
||||
@ -166,19 +163,21 @@ public class NetworkDiscovery implements Discovery, ServiceListener, cc.arduino.
|
||||
port.setPrefs(prefs);
|
||||
port.setLabel(label);
|
||||
|
||||
synchronized (this) {
|
||||
synchronized (boardPortsDiscoveredWithJmDNS) {
|
||||
removeDuplicateBoards(port);
|
||||
ports.add(port);
|
||||
boardPortsDiscoveredWithJmDNS.add(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeDuplicateBoards(BoardPort newBoard) {
|
||||
Iterator<BoardPort> iterator = ports.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
BoardPort board = iterator.next();
|
||||
if (newBoard.getAddress().equals(board.getAddress())) {
|
||||
iterator.remove();
|
||||
synchronized (boardPortsDiscoveredWithJmDNS) {
|
||||
Iterator<BoardPort> iterator = boardPortsDiscoveredWithJmDNS.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
BoardPort board = iterator.next();
|
||||
if (newBoard.getAddress().equals(board.getAddress())) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,86 +31,49 @@ package cc.arduino.packages.discoverers;
|
||||
|
||||
import cc.arduino.packages.BoardPort;
|
||||
import cc.arduino.packages.Discovery;
|
||||
import processing.app.BaseNoGui;
|
||||
import processing.app.Platform;
|
||||
import processing.app.Serial;
|
||||
import processing.app.debug.TargetBoard;
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
import cc.arduino.packages.discoverers.serial.SerialBoardsLister;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
|
||||
public class SerialDiscovery implements Discovery {
|
||||
|
||||
static {
|
||||
//makes transifex happy
|
||||
_("Uncertified");
|
||||
private Timer serialBoardsListerTimer;
|
||||
private final List<BoardPort> serialBoardPorts;
|
||||
|
||||
public SerialDiscovery() {
|
||||
this.serialBoardPorts = new LinkedList<BoardPort>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BoardPort> discovery() {
|
||||
Platform os = BaseNoGui.getPlatform();
|
||||
String devicesListOutput = os.preListAllCandidateDevices();
|
||||
public List<BoardPort> listDiscoveredBoards() {
|
||||
return getSerialBoardPorts();
|
||||
}
|
||||
|
||||
List<BoardPort> res = new ArrayList<BoardPort>();
|
||||
|
||||
List<String> ports = Serial.list();
|
||||
|
||||
for (String port : ports) {
|
||||
Map<String, Object> boardData = os.resolveDeviceAttachedTo(port, BaseNoGui.packages, devicesListOutput);
|
||||
|
||||
BoardPort boardPort = new BoardPort();
|
||||
boardPort.setAddress(port);
|
||||
boardPort.setProtocol("serial");
|
||||
|
||||
String label = port;
|
||||
|
||||
PreferencesMap prefs = new PreferencesMap();
|
||||
|
||||
if (boardData != null) {
|
||||
prefs.put("vid", boardData.get("vid").toString());
|
||||
prefs.put("pid", boardData.get("pid").toString());
|
||||
|
||||
TargetBoard board = (TargetBoard) boardData.get("board");
|
||||
if (board != null) {
|
||||
String warningKey = "vid." + boardData.get("vid").toString() + ".warning";
|
||||
String warning = board.getPreferences().get(warningKey);
|
||||
prefs.put("warning", warning);
|
||||
|
||||
String boardName = board.getName();
|
||||
if (boardName != null) {
|
||||
if (warning != null) {
|
||||
label += " (" + boardName + " - " + _(warning) + ")";
|
||||
} else {
|
||||
label += " (" + boardName + ")";
|
||||
}
|
||||
}
|
||||
boardPort.setBoardName(boardName);
|
||||
}
|
||||
}
|
||||
|
||||
boardPort.setLabel(label);
|
||||
boardPort.setPrefs(prefs);
|
||||
|
||||
res.add(boardPort);
|
||||
public List<BoardPort> getSerialBoardPorts() {
|
||||
synchronized (serialBoardPorts) {
|
||||
return new LinkedList<BoardPort>(serialBoardPorts);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPreferences(PreferencesMap options) {
|
||||
public void setSerialBoardPorts(List<BoardPort> newSerialBoardPorts) {
|
||||
synchronized (serialBoardPorts) {
|
||||
serialBoardPorts.clear();
|
||||
serialBoardPorts.addAll(newSerialBoardPorts);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.serialBoardsListerTimer = new Timer(SerialBoardsLister.class.getName());
|
||||
new SerialBoardsLister(this).start(serialBoardsListerTimer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
this.serialBoardsListerTimer.purge();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
|
||||
*/
|
||||
|
||||
package cc.arduino.packages.discoverers.network;
|
||||
|
||||
import cc.arduino.packages.BoardPort;
|
||||
import cc.arduino.packages.discoverers.NetworkDiscovery;
|
||||
import processing.app.helpers.NetUtils;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.*;
|
||||
|
||||
public class BoardReachabilityFilter extends TimerTask {
|
||||
|
||||
private final NetworkDiscovery networkDiscovery;
|
||||
|
||||
public BoardReachabilityFilter(NetworkDiscovery networkDiscovery) {
|
||||
this.networkDiscovery = networkDiscovery;
|
||||
}
|
||||
|
||||
public void start(Timer timer) {
|
||||
timer.schedule(this, 0, 3000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
List<BoardPort> boardPorts = networkDiscovery.getBoardPortsDiscoveredWithJmDNS();
|
||||
|
||||
Iterator<BoardPort> boardPortIterator = boardPorts.iterator();
|
||||
while (boardPortIterator.hasNext()) {
|
||||
try {
|
||||
BoardPort board = boardPortIterator.next();
|
||||
|
||||
InetAddress inetAddress = InetAddress.getByName(board.getAddress());
|
||||
int broadcastedPort = Integer.valueOf(board.getPrefs().get("port"));
|
||||
|
||||
List<Integer> ports = new LinkedList<Integer>();
|
||||
ports.add(broadcastedPort);
|
||||
|
||||
//dirty code: allows non up to date yuns to be discovered. Newer yuns will broadcast port 22
|
||||
if (broadcastedPort == 80) {
|
||||
ports.add(0, 22);
|
||||
}
|
||||
|
||||
boolean reachable = NetUtils.isReachable(inetAddress, ports);
|
||||
if (!reachable) {
|
||||
boardPortIterator.remove();
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
boardPortIterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
networkDiscovery.setReachableBoardPorts(boardPorts);
|
||||
}
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
|
||||
*/
|
||||
|
||||
package cc.arduino.packages.discoverers.serial;
|
||||
|
||||
import cc.arduino.packages.BoardPort;
|
||||
import cc.arduino.packages.discoverers.SerialDiscovery;
|
||||
import processing.app.BaseNoGui;
|
||||
import processing.app.Platform;
|
||||
import processing.app.Serial;
|
||||
import processing.app.debug.TargetBoard;
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class SerialBoardsLister extends TimerTask {
|
||||
|
||||
private static final int MAX_TIME_AWAITING_FOR_PACKAGES = 5000;
|
||||
|
||||
private final SerialDiscovery serialDiscovery;
|
||||
|
||||
public SerialBoardsLister(SerialDiscovery serialDiscovery) {
|
||||
this.serialDiscovery = serialDiscovery;
|
||||
}
|
||||
|
||||
public void start(Timer timer) {
|
||||
timer.schedule(this, 0, 3000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
int sleptFor = 0;
|
||||
while (BaseNoGui.packages == null && sleptFor <= MAX_TIME_AWAITING_FOR_PACKAGES) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
sleptFor += 1000;
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
Platform platform = BaseNoGui.getPlatform();
|
||||
if (platform == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<BoardPort> boardPorts = new LinkedList<BoardPort>();
|
||||
|
||||
List<String> ports = Serial.list();
|
||||
|
||||
String devicesListOutput = null;
|
||||
if (!ports.isEmpty()) {
|
||||
devicesListOutput = platform.preListAllCandidateDevices();
|
||||
}
|
||||
|
||||
for (String port : ports) {
|
||||
Map<String, Object> boardData = platform.resolveDeviceAttachedTo(port, BaseNoGui.packages, devicesListOutput);
|
||||
|
||||
BoardPort boardPort = new BoardPort();
|
||||
boardPort.setAddress(port);
|
||||
boardPort.setProtocol("serial");
|
||||
|
||||
String label = port;
|
||||
|
||||
PreferencesMap prefs = new PreferencesMap();
|
||||
|
||||
if (boardData != null) {
|
||||
prefs.put("vid", boardData.get("vid").toString());
|
||||
prefs.put("pid", boardData.get("pid").toString());
|
||||
|
||||
TargetBoard board = (TargetBoard) boardData.get("board");
|
||||
if (board != null) {
|
||||
String boardName = board.getName();
|
||||
if (boardName != null) {
|
||||
label += " (" + boardName + ")";
|
||||
}
|
||||
boardPort.setBoardName(boardName);
|
||||
}
|
||||
}
|
||||
|
||||
boardPort.setLabel(label);
|
||||
boardPort.setPrefs(prefs);
|
||||
|
||||
boardPorts.add(boardPort);
|
||||
}
|
||||
|
||||
serialDiscovery.setSerialBoardPorts(boardPorts);
|
||||
}
|
||||
}
|
@ -119,7 +119,10 @@ public class SSHUploader extends Uploader {
|
||||
private boolean runAVRDude(SSH ssh) throws IOException, JSchException {
|
||||
TargetPlatform targetPlatform = BaseNoGui.getTargetPlatform();
|
||||
PreferencesMap prefs = PreferencesData.getMap();
|
||||
prefs.putAll(BaseNoGui.getBoardPreferences());
|
||||
PreferencesMap boardPreferences = BaseNoGui.getBoardPreferences();
|
||||
if (boardPreferences != null) {
|
||||
prefs.putAll(boardPreferences);
|
||||
}
|
||||
prefs.putAll(targetPlatform.getTool(prefs.get("upload.tool")));
|
||||
|
||||
String additionalParams = verbose ? prefs.get("upload.params.verbose") : prefs.get("upload.params.quiet");
|
||||
|
@ -60,7 +60,10 @@ public class SerialUploader extends Uploader {
|
||||
// FIXME: Preferences should be reorganized
|
||||
TargetPlatform targetPlatform = BaseNoGui.getTargetPlatform();
|
||||
PreferencesMap prefs = PreferencesData.getMap();
|
||||
prefs.putAll(BaseNoGui.getBoardPreferences());
|
||||
PreferencesMap boardPreferences = BaseNoGui.getBoardPreferences();
|
||||
if (boardPreferences != null) {
|
||||
prefs.putAll(boardPreferences);
|
||||
}
|
||||
String tool = prefs.getOrExcept("upload.tool");
|
||||
if (tool.contains(":")) {
|
||||
String[] split = tool.split(":", 2);
|
||||
@ -116,7 +119,7 @@ public class SerialUploader extends Uploader {
|
||||
if (verbose)
|
||||
System.out.println(
|
||||
I18n.format(_("Forcing reset using 1200bps open/close on port {0}"), uploadPort));
|
||||
Serial.touchPort(uploadPort, 1200);
|
||||
Serial.touchForCDCReset(uploadPort);
|
||||
}
|
||||
Thread.sleep(400);
|
||||
if (waitForUploadPort) {
|
||||
@ -242,13 +245,16 @@ public class SerialUploader extends Uploader {
|
||||
}
|
||||
|
||||
PreferencesMap prefs = PreferencesData.getMap();
|
||||
prefs.putAll(BaseNoGui.getBoardPreferences());
|
||||
PreferencesMap boardPreferences = BaseNoGui.getBoardPreferences();
|
||||
if (boardPreferences != null) {
|
||||
prefs.putAll(boardPreferences);
|
||||
}
|
||||
PreferencesMap programmerPrefs = targetPlatform.getProgrammer(programmer);
|
||||
if (programmerPrefs == null)
|
||||
throw new RunnerException(
|
||||
_("Please select a programmer from Tools->Programmer menu"));
|
||||
prefs.putAll(targetPlatform.getTool(programmerPrefs.getOrExcept("program.tool")));
|
||||
prefs.putAll(programmerPrefs);
|
||||
prefs.putAll(targetPlatform.getTool(prefs.getOrExcept("program.tool")));
|
||||
|
||||
prefs.put("build.path", buildPath);
|
||||
prefs.put("build.project_name", className);
|
||||
@ -295,7 +301,10 @@ public class SerialUploader extends Uploader {
|
||||
|
||||
// Build configuration for the current programmer
|
||||
PreferencesMap prefs = PreferencesData.getMap();
|
||||
prefs.putAll(BaseNoGui.getBoardPreferences());
|
||||
PreferencesMap boardPreferences = BaseNoGui.getBoardPreferences();
|
||||
if (boardPreferences != null) {
|
||||
prefs.putAll(boardPreferences);
|
||||
}
|
||||
prefs.putAll(programmerPrefs);
|
||||
|
||||
// Create configuration for bootloader tool
|
||||
|
303
arduino-core/src/cc/arduino/utils/ArchiveExtractor.java
Normal file
303
arduino-core/src/cc/arduino/utils/ArchiveExtractor.java
Normal file
@ -0,0 +1,303 @@
|
||||
/*
|
||||
* 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.utils;
|
||||
|
||||
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.ArchiveInputStream;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
|
||||
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
|
||||
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
|
||||
import processing.app.I18n;
|
||||
import processing.app.Platform;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
|
||||
public class ArchiveExtractor {
|
||||
|
||||
private final Platform platform;
|
||||
|
||||
public ArchiveExtractor(Platform platform) {
|
||||
assert platform != null;
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract <b>source</b> into <b>destFolder</b>. <b>source</b> file archive
|
||||
* format is autodetected from file extension.
|
||||
*
|
||||
* @param archiveFile
|
||||
* @param destFolder
|
||||
* @throws IOException
|
||||
*/
|
||||
public void extract(File archiveFile, File destFolder) throws IOException, InterruptedException {
|
||||
extract(archiveFile, destFolder, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract <b>source</b> into <b>destFolder</b>. <b>source</b> file archive
|
||||
* format is autodetected from file extension.
|
||||
*
|
||||
* @param archiveFile Archive file to extract
|
||||
* @param destFolder Destination folder
|
||||
* @param stripPath Number of path elements to strip from the paths contained in the
|
||||
* archived files
|
||||
* @throws IOException
|
||||
*/
|
||||
public void extract(File archiveFile, File destFolder, int stripPath) throws IOException, InterruptedException {
|
||||
extract(archiveFile, destFolder, stripPath, false);
|
||||
}
|
||||
|
||||
|
||||
public void extract(File archiveFile, File destFolder, int stripPath, boolean overwrite) throws IOException, InterruptedException {
|
||||
|
||||
// Folders timestamps must be set at the end of archive extraction
|
||||
// (because creating a file in a folder alters the folder's timestamp)
|
||||
Map<File, Long> foldersTimestamps = new HashMap<File, Long>();
|
||||
|
||||
ArchiveInputStream in = null;
|
||||
try {
|
||||
|
||||
// Create an ArchiveInputStream with the correct archiving algorithm
|
||||
if (archiveFile.getName().endsWith("tar.bz2")) {
|
||||
in = new TarArchiveInputStream(new BZip2CompressorInputStream(new FileInputStream(archiveFile)));
|
||||
} else if (archiveFile.getName().endsWith("zip")) {
|
||||
in = new ZipArchiveInputStream(new FileInputStream(archiveFile));
|
||||
} else if (archiveFile.getName().endsWith("tar.gz")) {
|
||||
in = new TarArchiveInputStream(new GzipCompressorInputStream(new FileInputStream(archiveFile)));
|
||||
} else if (archiveFile.getName().endsWith("tar")) {
|
||||
in = new TarArchiveInputStream(new FileInputStream(archiveFile));
|
||||
} else {
|
||||
throw new IOException("Archive format not supported.");
|
||||
}
|
||||
|
||||
String pathPrefix = "";
|
||||
|
||||
Map<File, File> hardLinks = new HashMap<File, File>();
|
||||
Map<File, Integer> hardLinksMode = new HashMap<File, Integer>();
|
||||
Map<File, String> symLinks = new HashMap<File, String>();
|
||||
Map<File, Long> symLinksModifiedTimes = new HashMap<File, Long>();
|
||||
|
||||
// Cycle through all the archive entries
|
||||
while (true) {
|
||||
ArchiveEntry entry = in.getNextEntry();
|
||||
if (entry == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Extract entry info
|
||||
long size = entry.getSize();
|
||||
String name = entry.getName();
|
||||
boolean isDirectory = entry.isDirectory();
|
||||
boolean isLink = false;
|
||||
boolean isSymLink = false;
|
||||
String linkName = null;
|
||||
Integer mode = null;
|
||||
long modifiedTime = entry.getLastModifiedDate().getTime();
|
||||
|
||||
{
|
||||
// Skip MacOSX metadata
|
||||
// http://superuser.com/questions/61185/why-do-i-get-files-like-foo-in-my-tarball-on-os-x
|
||||
int slash = name.lastIndexOf('/');
|
||||
if (slash == -1) {
|
||||
if (name.startsWith("._")) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (name.substring(slash + 1).startsWith("._")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Skip git metadata
|
||||
// http://www.unix.com/unix-for-dummies-questions-and-answers/124958-file-pax_global_header-means-what.html
|
||||
if (name.contains("pax_global_header")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry instanceof TarArchiveEntry) {
|
||||
TarArchiveEntry tarEntry = (TarArchiveEntry) entry;
|
||||
mode = tarEntry.getMode();
|
||||
isLink = tarEntry.isLink();
|
||||
isSymLink = tarEntry.isSymbolicLink();
|
||||
linkName = tarEntry.getLinkName();
|
||||
}
|
||||
|
||||
// On the first archive entry, if requested, detect the common path
|
||||
// prefix to be stripped from filenames
|
||||
if (stripPath > 0 && pathPrefix.isEmpty()) {
|
||||
int slash = 0;
|
||||
while (stripPath > 0) {
|
||||
slash = name.indexOf("/", slash);
|
||||
if (slash == -1) {
|
||||
throw new IOException("Invalid archive: it must contains a single root folder");
|
||||
}
|
||||
slash++;
|
||||
stripPath--;
|
||||
}
|
||||
pathPrefix = name.substring(0, slash);
|
||||
}
|
||||
|
||||
// Strip the common path prefix when requested
|
||||
if (!name.startsWith(pathPrefix)) {
|
||||
throw new IOException("Invalid archive: it must contains a single root folder while file " + name + " is outside " + pathPrefix);
|
||||
}
|
||||
name = name.substring(pathPrefix.length());
|
||||
if (name.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
File outputFile = new File(destFolder, name);
|
||||
|
||||
File outputLinkedFile = null;
|
||||
if (isLink) {
|
||||
if (!linkName.startsWith(pathPrefix)) {
|
||||
throw new IOException("Invalid archive: it must contains a single root folder while file " + linkName + " is outside " + pathPrefix);
|
||||
}
|
||||
linkName = linkName.substring(pathPrefix.length());
|
||||
outputLinkedFile = new File(destFolder, linkName);
|
||||
}
|
||||
if (isSymLink) {
|
||||
// Symbolic links are referenced with relative paths
|
||||
outputLinkedFile = new File(linkName);
|
||||
if (outputLinkedFile.isAbsolute()) {
|
||||
System.err.println(I18n.format(_("Warning: file {0} links to an absolute path {1}"), outputFile, outputLinkedFile));
|
||||
System.err.println();
|
||||
}
|
||||
}
|
||||
|
||||
// Safety check
|
||||
if (isDirectory) {
|
||||
if (outputFile.isFile() && !overwrite) {
|
||||
throw new IOException("Can't create folder " + outputFile + ", a file with the same name exists!");
|
||||
}
|
||||
} else {
|
||||
// - isLink
|
||||
// - isSymLink
|
||||
// - anything else
|
||||
if (outputFile.exists() && !overwrite) {
|
||||
throw new IOException("Can't extract file " + outputFile + ", file already exists!");
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the entry
|
||||
if (isDirectory) {
|
||||
if (!outputFile.exists() && !outputFile.mkdirs()) {
|
||||
throw new IOException("Could not create folder: " + outputFile);
|
||||
}
|
||||
foldersTimestamps.put(outputFile, modifiedTime);
|
||||
} else if (isLink) {
|
||||
hardLinks.put(outputFile, outputLinkedFile);
|
||||
hardLinksMode.put(outputFile, mode);
|
||||
} else if (isSymLink) {
|
||||
symLinks.put(outputFile, linkName);
|
||||
symLinksModifiedTimes.put(outputFile, modifiedTime);
|
||||
} else {
|
||||
// Create the containing folder if not exists
|
||||
if (!outputFile.getParentFile().isDirectory()) {
|
||||
outputFile.getParentFile().mkdirs();
|
||||
}
|
||||
copyStreamToFile(in, size, outputFile);
|
||||
outputFile.setLastModified(modifiedTime);
|
||||
}
|
||||
|
||||
// Set file/folder permission
|
||||
if (mode != null && !isSymLink && outputFile.exists()) {
|
||||
platform.chmod(outputFile, mode);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<File, File> entry : hardLinks.entrySet()) {
|
||||
if (entry.getKey().exists() && overwrite) {
|
||||
entry.getKey().delete();
|
||||
}
|
||||
platform.link(entry.getValue(), entry.getKey());
|
||||
Integer mode = hardLinksMode.get(entry.getKey());
|
||||
if (mode != null) {
|
||||
platform.chmod(entry.getKey(), mode);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<File, String> entry : symLinks.entrySet()) {
|
||||
if (entry.getKey().exists() && overwrite) {
|
||||
entry.getKey().delete();
|
||||
}
|
||||
platform.symlink(entry.getValue(), entry.getKey());
|
||||
entry.getKey().setLastModified(symLinksModifiedTimes.get(entry.getKey()));
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Set folders timestamps
|
||||
for (File folder : foldersTimestamps.keySet()) {
|
||||
folder.setLastModified(foldersTimestamps.get(folder));
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyStreamToFile(InputStream in, long size, File outputFile) throws IOException {
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(outputFile);
|
||||
// if size is not available, copy until EOF...
|
||||
if (size == -1) {
|
||||
byte buffer[] = new byte[4096];
|
||||
int length;
|
||||
while ((length = in.read(buffer)) != -1) {
|
||||
fos.write(buffer, 0, length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// ...else copy just the needed amount of bytes
|
||||
byte buffer[] = new byte[4096];
|
||||
while (size > 0) {
|
||||
int length = in.read(buffer);
|
||||
if (length <= 0) {
|
||||
throw new IOException("Error while extracting file " + outputFile.getAbsolutePath());
|
||||
}
|
||||
fos.write(buffer, 0, length);
|
||||
size -= length;
|
||||
}
|
||||
} finally {
|
||||
if (fos != null) {
|
||||
fos.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
76
arduino-core/src/cc/arduino/utils/FileHash.java
Normal file
76
arduino-core/src/cc/arduino/utils/FileHash.java
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class FileHash {
|
||||
|
||||
/**
|
||||
* Calculate a message digest of a file using the algorithm specified. The
|
||||
* result is a string containing the algorithm name followed by ":" and by the
|
||||
* resulting hash in hex.
|
||||
*
|
||||
* @param file
|
||||
* @param algorithm For example "SHA-256"
|
||||
* @return The algorithm followed by ":" and the hash, for example:<br />
|
||||
* "SHA-256:ee6796513086080cca078cbb383f543c5e508b647a71c9d6f39b7bca41071883"
|
||||
* @throws IOException
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
public static String hash(File file, String algorithm) throws IOException, NoSuchAlgorithmException {
|
||||
FileInputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(file);
|
||||
byte buff[] = new byte[10240];
|
||||
MessageDigest digest = MessageDigest.getInstance(algorithm);
|
||||
while (in.available() > 0) {
|
||||
int read = in.read(buff);
|
||||
digest.update(buff, 0, read);
|
||||
}
|
||||
byte[] hash = digest.digest();
|
||||
String res = "";
|
||||
for (byte b : hash) {
|
||||
int c = b & 0xFF;
|
||||
if (c < 0x10)
|
||||
res += "0";
|
||||
res += Integer.toHexString(c);
|
||||
}
|
||||
return algorithm + ":" + res;
|
||||
} finally {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
74
arduino-core/src/cc/arduino/utils/MultiStepProgress.java
Normal file
74
arduino-core/src/cc/arduino/utils/MultiStepProgress.java
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.utils;
|
||||
|
||||
public class MultiStepProgress implements Progress {
|
||||
|
||||
private final double steps;
|
||||
|
||||
private double step;
|
||||
private double stepProgress;
|
||||
|
||||
String status;
|
||||
|
||||
public MultiStepProgress(int _steps) {
|
||||
steps = _steps;
|
||||
step = 0.0;
|
||||
stepProgress = 0.0;
|
||||
}
|
||||
|
||||
public double getGlobalProgress() {
|
||||
return (step + stepProgress) / steps;
|
||||
}
|
||||
|
||||
public void stepDone() {
|
||||
step += 100.0;
|
||||
setProgress(0.0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgress(double progress) {
|
||||
stepProgress = progress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStatus(String _status) {
|
||||
status = _status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getProgress() {
|
||||
return getGlobalProgress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
41
arduino-core/src/cc/arduino/utils/Progress.java
Normal file
41
arduino-core/src/cc/arduino/utils/Progress.java
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.utils;
|
||||
|
||||
public interface Progress {
|
||||
|
||||
void setProgress(double progress);
|
||||
|
||||
double getProgress();
|
||||
|
||||
void setStatus(String _status);
|
||||
|
||||
String getStatus();
|
||||
|
||||
}
|
17
arduino-core/src/cc/arduino/utils/ReverseComparator.java
Normal file
17
arduino-core/src/cc/arduino/utils/ReverseComparator.java
Normal file
@ -0,0 +1,17 @@
|
||||
package cc.arduino.utils;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class ReverseComparator<T> implements Comparator<T> {
|
||||
|
||||
private final Comparator<T> orig;
|
||||
|
||||
public ReverseComparator(Comparator<T> orig) {
|
||||
this.orig = orig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(T t, T t1) {
|
||||
return -1 * orig.compare(t, t1);
|
||||
}
|
||||
}
|
255
arduino-core/src/cc/arduino/utils/network/FileDownloader.java
Normal file
255
arduino-core/src/cc/arduino/utils/network/FileDownloader.java
Normal file
@ -0,0 +1,255 @@
|
||||
/*
|
||||
* 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.utils.network;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import processing.app.PreferencesData;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URL;
|
||||
import java.util.Observable;
|
||||
|
||||
public class FileDownloader extends Observable {
|
||||
|
||||
public enum Status {
|
||||
CONNECTING, //
|
||||
CONNECTION_TIMEOUT_ERROR, //
|
||||
DOWNLOADING, //
|
||||
COMPLETE, //
|
||||
CANCELLED, //
|
||||
ERROR, //
|
||||
}
|
||||
|
||||
private Status status;
|
||||
private long initialSize;
|
||||
private Long downloadSize = null;
|
||||
private long downloaded;
|
||||
private final URL downloadUrl;
|
||||
|
||||
private final File outputFile;
|
||||
private InputStream stream = null;
|
||||
private Exception error;
|
||||
|
||||
public FileDownloader(URL url, File file) {
|
||||
downloadUrl = url;
|
||||
outputFile = file;
|
||||
downloaded = 0;
|
||||
initialSize = 0;
|
||||
}
|
||||
|
||||
public long getInitialSize() {
|
||||
return initialSize;
|
||||
}
|
||||
|
||||
public Long getDownloadSize() {
|
||||
return downloadSize;
|
||||
}
|
||||
|
||||
public void setDownloadSize(Long downloadSize) {
|
||||
this.downloadSize = downloadSize;
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
public long getDownloaded() {
|
||||
return downloaded;
|
||||
}
|
||||
|
||||
private void setDownloaded(long downloaded) {
|
||||
this.downloaded = downloaded;
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
public float getProgress() {
|
||||
if (downloadSize == null)
|
||||
return 0;
|
||||
if (downloadSize == 0)
|
||||
return 100;
|
||||
return ((float) downloaded / downloadSize) * 100;
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Status status) {
|
||||
this.status = status;
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
public void download() throws InterruptedException {
|
||||
RandomAccessFile file = null;
|
||||
|
||||
try {
|
||||
// Open file and seek to the end of it
|
||||
file = new RandomAccessFile(outputFile, "rw");
|
||||
initialSize = file.length();
|
||||
file.seek(initialSize);
|
||||
|
||||
setStatus(Status.CONNECTING);
|
||||
|
||||
System.getProperties().remove("http.proxyHost");
|
||||
System.getProperties().remove("http.proxyPort");
|
||||
System.getProperties().remove("https.proxyHost");
|
||||
System.getProperties().remove("https.proxyPort");
|
||||
System.getProperties().remove("http.proxyUser");
|
||||
System.getProperties().remove("http.proxyPassword");
|
||||
|
||||
if (PreferencesData.has("proxy.http.server") && PreferencesData.get("proxy.http.server") != null && !PreferencesData.get("proxy.http.server").equals("")) {
|
||||
System.getProperties().put("http.proxyHost", PreferencesData.get("proxy.http.server"));
|
||||
System.getProperties().put("http.proxyPort", PreferencesData.get("proxy.http.port"));
|
||||
}
|
||||
if (PreferencesData.has("proxy.https.server") && PreferencesData.get("proxy.https.server") != null && !PreferencesData.get("proxy.https.server").equals("")) {
|
||||
System.getProperties().put("https.proxyHost", PreferencesData.get("proxy.https.server"));
|
||||
System.getProperties().put("https.proxyPort", PreferencesData.get("proxy.https.port"));
|
||||
}
|
||||
if (PreferencesData.has("proxy.user") && PreferencesData.get("proxy.user") != null && !PreferencesData.get("proxy.user").equals("")) {
|
||||
System.getProperties().put("http.proxyUser", PreferencesData.get("proxy.user"));
|
||||
System.getProperties().put("http.proxyPassword", PreferencesData.get("proxy.password"));
|
||||
System.getProperties().put("https.proxyUser", PreferencesData.get("proxy.user"));
|
||||
System.getProperties().put("https.proxyPassword", PreferencesData.get("proxy.password"));
|
||||
}
|
||||
|
||||
HttpURLConnection connection = (HttpURLConnection) downloadUrl.openConnection();
|
||||
|
||||
if (downloadUrl.getUserInfo() != null) {
|
||||
String auth = "Basic " + new String(new Base64().encode(downloadUrl.getUserInfo().getBytes()));
|
||||
connection.setRequestProperty("Authorization", auth);
|
||||
}
|
||||
|
||||
connection.setRequestProperty("Range", "bytes=" + initialSize + "-");
|
||||
connection.setConnectTimeout(5000);
|
||||
setDownloaded(0);
|
||||
|
||||
// Connect
|
||||
connection.connect();
|
||||
int resp = connection.getResponseCode();
|
||||
|
||||
if (resp == HttpURLConnection.HTTP_MOVED_PERM || resp == HttpURLConnection.HTTP_MOVED_TEMP) {
|
||||
String newUrl = connection.getHeaderField("Location");
|
||||
|
||||
// open the new connnection again
|
||||
connection = (HttpURLConnection) new URL(newUrl).openConnection();
|
||||
if (downloadUrl.getUserInfo() != null) {
|
||||
String auth = "Basic " + new String(new Base64().encode(downloadUrl.getUserInfo().getBytes()));
|
||||
connection.setRequestProperty("Authorization", auth);
|
||||
}
|
||||
|
||||
connection.setRequestProperty("Range", "bytes=" + initialSize + "-");
|
||||
connection.setConnectTimeout(5000);
|
||||
|
||||
connection.connect();
|
||||
resp = connection.getResponseCode();
|
||||
}
|
||||
|
||||
if (resp < 200 || resp >= 300) {
|
||||
throw new IOException("Recevied invalid http status code from server: " + resp);
|
||||
}
|
||||
|
||||
// Check for valid content length.
|
||||
long len = connection.getContentLength();
|
||||
if (len >= 0) {
|
||||
setDownloadSize(len);
|
||||
}
|
||||
setStatus(Status.DOWNLOADING);
|
||||
|
||||
synchronized (this) {
|
||||
stream = connection.getInputStream();
|
||||
}
|
||||
byte buffer[] = new byte[10240];
|
||||
while (status == Status.DOWNLOADING) {
|
||||
int read = stream.read(buffer);
|
||||
if (read == -1)
|
||||
break;
|
||||
|
||||
file.write(buffer, 0, read);
|
||||
setDownloaded(getDownloaded() + read);
|
||||
|
||||
if (Thread.interrupted())
|
||||
throw new InterruptedException();
|
||||
}
|
||||
|
||||
if (getDownloadSize() != null) {
|
||||
if (getDownloaded() < getDownloadSize())
|
||||
throw new Exception("Incomplete download");
|
||||
}
|
||||
setStatus(Status.COMPLETE);
|
||||
} catch (InterruptedException e) {
|
||||
setStatus(Status.CANCELLED);
|
||||
// lets InterruptedException go up to the caller
|
||||
throw e;
|
||||
|
||||
} catch (SocketTimeoutException e) {
|
||||
setStatus(Status.CONNECTION_TIMEOUT_ERROR);
|
||||
setError(e);
|
||||
|
||||
} catch (Exception e) {
|
||||
setStatus(Status.ERROR);
|
||||
setError(e);
|
||||
|
||||
} finally {
|
||||
if (file != null) {
|
||||
try {
|
||||
file.close();
|
||||
} catch (Exception e) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (Exception e) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setError(Exception e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
public Exception getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public boolean isCompleted() {
|
||||
return status == Status.COMPLETE;
|
||||
}
|
||||
}
|
@ -1,45 +1,53 @@
|
||||
package processing.app;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
import cc.arduino.contributions.SignatureVerificationFailedException;
|
||||
import cc.arduino.contributions.libraries.LibrariesIndexer;
|
||||
import cc.arduino.contributions.packages.ContributedTool;
|
||||
import cc.arduino.contributions.packages.ContributionsIndexer;
|
||||
import cc.arduino.files.DeleteFilesOnShutdown;
|
||||
import cc.arduino.packages.DiscoveryManager;
|
||||
import cc.arduino.packages.Uploader;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import org.apache.commons.logging.impl.LogFactoryImpl;
|
||||
import org.apache.commons.logging.impl.NoOpLog;
|
||||
import processing.app.debug.Compiler;
|
||||
import processing.app.debug.*;
|
||||
import processing.app.helpers.*;
|
||||
import processing.app.helpers.filefilters.OnlyDirs;
|
||||
import processing.app.helpers.filefilters.OnlyFilesWithExtension;
|
||||
import processing.app.legacy.PApplet;
|
||||
import processing.app.packages.LibraryList;
|
||||
import processing.app.packages.UserLibrary;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.*;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.commons.logging.impl.LogFactoryImpl;
|
||||
import org.apache.commons.logging.impl.NoOpLog;
|
||||
|
||||
import cc.arduino.packages.DiscoveryManager;
|
||||
import cc.arduino.packages.Uploader;
|
||||
|
||||
import processing.app.debug.Compiler;
|
||||
import processing.app.debug.TargetBoard;
|
||||
import processing.app.debug.TargetPackage;
|
||||
import processing.app.debug.TargetPlatform;
|
||||
import processing.app.debug.TargetPlatformException;
|
||||
import processing.app.helpers.BasicUserNotifier;
|
||||
import processing.app.helpers.CommandlineParser;
|
||||
import processing.app.helpers.OSUtils;
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
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 static processing.app.I18n._;
|
||||
|
||||
public class BaseNoGui {
|
||||
|
||||
/** Version string to be used for build */
|
||||
public static final int REVISION = 10601;
|
||||
public static final int REVISION = 10605;
|
||||
/** Extended version string displayed on GUI */
|
||||
static String VERSION_NAME = "1.6.1";
|
||||
public static final String VERSION_NAME = "1.6.5";
|
||||
public static final String VERSION_NAME_LONG;
|
||||
|
||||
static {
|
||||
String versionNameLong = VERSION_NAME;
|
||||
File hourlyBuildTxt = new File(getContentFile("lib"), "hourlyBuild.txt");
|
||||
if (hourlyBuildTxt.exists() && hourlyBuildTxt.canRead()) {
|
||||
versionNameLong += " Hourly Build";
|
||||
try {
|
||||
versionNameLong += " " + FileUtils.readFileToString(hourlyBuildTxt).trim();
|
||||
} catch (IOException e) {
|
||||
//noop
|
||||
}
|
||||
}
|
||||
VERSION_NAME_LONG = versionNameLong;
|
||||
}
|
||||
|
||||
static File buildFolder;
|
||||
|
||||
@ -54,11 +62,12 @@ public class BaseNoGui {
|
||||
static private File toolsFolder;
|
||||
|
||||
// maps #included files to their library folder
|
||||
public static Map<String, Library> importToLibraryTable;
|
||||
public static Map<String, LibraryList> importToLibraryTable;
|
||||
|
||||
// maps library name to their library folder
|
||||
static private LibraryList libraries;
|
||||
|
||||
// XXX: Remove this field
|
||||
static private List<File> librariesFolders;
|
||||
|
||||
static UserNotifier notifier = new BasicUserNotifier();
|
||||
@ -68,9 +77,11 @@ public class BaseNoGui {
|
||||
static Platform platform;
|
||||
|
||||
static File portableFolder = null;
|
||||
|
||||
static final String portableSketchbookFolder = "sketchbook";
|
||||
|
||||
public 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
|
||||
// directory when starting the IDE (which is not the same as the
|
||||
@ -139,7 +150,7 @@ public class BaseNoGui {
|
||||
//File folder = new File(getTempFolder(), "build");
|
||||
//if (!folder.exists()) folder.mkdirs();
|
||||
buildFolder = createTempFolder("build");
|
||||
buildFolder.deleteOnExit();
|
||||
DeleteFilesOnShutdown.add(buildFolder);
|
||||
}
|
||||
}
|
||||
return buildFolder;
|
||||
@ -238,13 +249,6 @@ public class BaseNoGui {
|
||||
return librariesFolders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an InputStream for a file inside the Processing lib folder.
|
||||
*/
|
||||
static public InputStream getLibStream(String filename) throws IOException {
|
||||
return new FileInputStream(new File(getContentFile("lib"), filename));
|
||||
}
|
||||
|
||||
static public Platform getPlatform() {
|
||||
return platform;
|
||||
}
|
||||
@ -403,9 +407,8 @@ public class BaseNoGui {
|
||||
}
|
||||
|
||||
static public LibraryList getUserLibs() {
|
||||
if (libraries == null)
|
||||
return new LibraryList();
|
||||
return libraries.filterLibrariesInSubfolder(getSketchbookFolder());
|
||||
LibraryList libs = BaseNoGui.librariesIndexer.getInstalledLibraries();
|
||||
return libs.filterLibrariesInSubfolder(getSketchbookFolder());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -421,7 +424,7 @@ public class BaseNoGui {
|
||||
return list;
|
||||
}
|
||||
|
||||
static public void init(String[] args) {
|
||||
static public void init(String[] args) throws Exception {
|
||||
getPlatform().init();
|
||||
|
||||
String sketchbookPath = getSketchbookPath();
|
||||
@ -508,7 +511,7 @@ public class BaseNoGui {
|
||||
// - calls Sketch.build(verbose=false) that calls Sketch.ensureExistence(), set progressListener and calls Compiler.build()
|
||||
// - calls Sketch.upload() (see later...)
|
||||
if (!data.getFolder().exists()) showError(_("No sketch"), _("Can't find the sketch in the specified path"), null);
|
||||
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild());
|
||||
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild(), false);
|
||||
if (suggestedClassName == null) showError(_("Error while verifying"), _("An error occurred while verifying the sketch"), null);
|
||||
showMessage(_("Done compiling"), _("Done compiling"));
|
||||
|
||||
@ -553,7 +556,7 @@ public class BaseNoGui {
|
||||
// if (!data.getFolder().exists()) showError(...);
|
||||
// String ... = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, verbose);
|
||||
if (!data.getFolder().exists()) showError(_("No sketch"), _("Can't find the sketch in the specified path"), null);
|
||||
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild());
|
||||
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild(), false);
|
||||
if (suggestedClassName == null) showError(_("Error while verifying"), _("An error occurred while verifying the sketch"), null);
|
||||
showMessage(_("Done compiling"), _("Done compiling"));
|
||||
} catch (Exception e) {
|
||||
@ -582,13 +585,77 @@ public class BaseNoGui {
|
||||
Logger.getLogger("javax.jmdns").setLevel(Level.OFF);
|
||||
}
|
||||
|
||||
static public void initPackages() {
|
||||
static public void initPackages() throws Exception {
|
||||
indexer = new ContributionsIndexer(BaseNoGui.getSettingsFolder());
|
||||
File indexFile = indexer.getIndexFile("package_index.json");
|
||||
File defaultPackageJsonFile = new File(getContentFile("dist"), "package_index.json");
|
||||
if (!indexFile.isFile() || (defaultPackageJsonFile.isFile() && defaultPackageJsonFile.lastModified() > indexFile.lastModified())) {
|
||||
FileUtils.copyFile(defaultPackageJsonFile, indexFile);
|
||||
} else if (!indexFile.isFile()) {
|
||||
// Otherwise create an empty packages index
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
out = new FileOutputStream(indexFile);
|
||||
out.write("{ \"packages\" : [ ] }".getBytes());
|
||||
out.close();
|
||||
} finally {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File indexSignatureFile = indexer.getIndexFile("package_index.json.sig");
|
||||
File defaultPackageJsonSignatureFile = new File(getContentFile("dist"), "package_index.json.sig");
|
||||
if (!indexSignatureFile.isFile() || (defaultPackageJsonSignatureFile.isFile() && defaultPackageJsonSignatureFile.lastModified() > indexSignatureFile.lastModified())) {
|
||||
FileUtils.copyFile(defaultPackageJsonSignatureFile, indexSignatureFile);
|
||||
}
|
||||
|
||||
try {
|
||||
indexer.parseIndex();
|
||||
} catch (JsonProcessingException e) {
|
||||
FileUtils.deleteIfExists(indexFile);
|
||||
FileUtils.deleteIfExists(indexSignatureFile);
|
||||
throw e;
|
||||
} catch (SignatureVerificationFailedException e) {
|
||||
FileUtils.deleteIfExists(indexFile);
|
||||
FileUtils.deleteIfExists(indexSignatureFile);
|
||||
throw e;
|
||||
}
|
||||
indexer.syncWithFilesystem(getHardwareFolder());
|
||||
|
||||
packages = new HashMap<String, TargetPackage>();
|
||||
loadHardware(getHardwareFolder());
|
||||
loadHardware(getSketchbookHardwareFolder());
|
||||
if (packages.size() == 0) {
|
||||
System.out.println(_("No valid configured cores found! Exiting..."));
|
||||
System.exit(3);
|
||||
loadContributedHardware(indexer);
|
||||
createToolPreferences(indexer);
|
||||
|
||||
librariesIndexer = new LibrariesIndexer(BaseNoGui.getSettingsFolder());
|
||||
File librariesIndexFile = librariesIndexer.getIndexFile();
|
||||
if (!librariesIndexFile.isFile()) {
|
||||
File defaultLibraryJsonFile = new File(getContentFile("dist"), "library_index.json");
|
||||
if (defaultLibraryJsonFile.isFile()) {
|
||||
FileUtils.copyFile(defaultLibraryJsonFile, librariesIndexFile);
|
||||
} else {
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
// Otherwise create an empty packages index
|
||||
out = new FileOutputStream(librariesIndexFile);
|
||||
out.write("{ \"libraries\" : [ ] }".getBytes());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
librariesIndexer.parseIndex();
|
||||
} catch (JsonProcessingException e) {
|
||||
FileUtils.deleteIfExists(librariesIndexFile);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@ -649,9 +716,9 @@ public class BaseNoGui {
|
||||
File subfolder = new File(folder, target);
|
||||
|
||||
try {
|
||||
packages.put(target, new TargetPackage(target, subfolder));
|
||||
packages.put(target, new LegacyTargetPackage(target, subfolder));
|
||||
} catch (TargetPlatformException e) {
|
||||
System.out.println("WARNING: Error loading hardware folder " + target);
|
||||
System.out.println("WARNING: Error loading hardware folder " + new File(folder, target));
|
||||
System.out.println(" " + e.getMessage());
|
||||
}
|
||||
}
|
||||
@ -670,6 +737,8 @@ public class BaseNoGui {
|
||||
if (args.length == 0)
|
||||
showError(_("No parameters"), _("No command line parameters found"), null);
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(DeleteFilesOnShutdown.INSTANCE));
|
||||
|
||||
initPlatform();
|
||||
|
||||
initPortableFolder();
|
||||
@ -683,9 +752,10 @@ public class BaseNoGui {
|
||||
examplesFolder = getContentFile("examples");
|
||||
toolsFolder = getContentFile("tools");
|
||||
librariesFolders = new ArrayList<File>();
|
||||
|
||||
// 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");
|
||||
@ -694,35 +764,69 @@ public class BaseNoGui {
|
||||
TargetPlatform referencedPlatform = getTargetPlatform(referencedCore, targetPlatform.getId());
|
||||
if (referencedPlatform != null) {
|
||||
File referencedPlatformFolder = referencedPlatform.getFolder();
|
||||
librariesFolders.add(new File(referencedPlatformFolder, "libraries"));
|
||||
// Add libraries folder for the referenced platform
|
||||
File folder = new File(referencedPlatformFolder, "libraries");
|
||||
librariesFolders.add(folder);
|
||||
}
|
||||
}
|
||||
File platformFolder = targetPlatform.getFolder();
|
||||
librariesFolders.add(new File(platformFolder, "libraries"));
|
||||
librariesFolders.add(getSketchbookLibrariesFolder());
|
||||
// Add libraries folder for the selected platform
|
||||
File folder = new File(platformFolder, "libraries");
|
||||
librariesFolders.add(folder);
|
||||
}
|
||||
|
||||
// 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.
|
||||
try {
|
||||
scanAndUpdateLibraries(librariesFolders);
|
||||
} catch (IOException e) {
|
||||
showWarning(_("Error"), _("Error loading libraries"), e);
|
||||
}
|
||||
BaseNoGui.librariesIndexer.setSketchbookLibrariesFolder(getSketchbookLibrariesFolder());
|
||||
BaseNoGui.librariesIndexer.setLibrariesFolders(librariesFolders);
|
||||
BaseNoGui.librariesIndexer.rescanLibraries();
|
||||
|
||||
populateImportToLibraryTable();
|
||||
}
|
||||
|
||||
static protected void loadContributedHardware(ContributionsIndexer indexer) throws TargetPlatformException {
|
||||
for (TargetPackage pack : indexer.createTargetPackages()) {
|
||||
packages.put(pack.getId(), pack);
|
||||
}
|
||||
}
|
||||
|
||||
static private void createToolPreferences(ContributionsIndexer indexer) {
|
||||
// Remove previous runtime preferences
|
||||
final String prefix = "runtime.tools.";
|
||||
PreferencesData.removeAllKeysWithPrefix(prefix);
|
||||
|
||||
for (ContributedTool tool : indexer.getInstalledTools()) {
|
||||
File installedFolder = tool.getDownloadableContribution().getInstalledFolder();
|
||||
if (installedFolder != null) {
|
||||
PreferencesData.set(prefix + tool.getName() + ".path", installedFolder.getAbsolutePath());
|
||||
PreferencesData.set(prefix + tool.getName() + "-" + tool.getVersion() + ".path", installedFolder.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public void populateImportToLibraryTable() {
|
||||
// Populate importToLibraryTable
|
||||
importToLibraryTable = new HashMap<String, Library>();
|
||||
for (Library lib : getLibraries()) {
|
||||
// Populate importToLibraryTable. Each header filename maps to
|
||||
// a list of libraries. Compiler.java will use only the first
|
||||
// library on each list. The others are used only to advise
|
||||
// user of ambiguously matched and duplicate libraries.
|
||||
importToLibraryTable = new HashMap<String, LibraryList>();
|
||||
for (UserLibrary lib : librariesIndexer.getInstalledLibraries()) {
|
||||
try {
|
||||
String headers[] = headerListFromIncludePath(lib.getSrcFolder());
|
||||
for (String header : headers) {
|
||||
Library old = importToLibraryTable.get(header);
|
||||
if (old != null) {
|
||||
LibraryList list = importToLibraryTable.get(header);
|
||||
if (list == null) {
|
||||
// This is the first library found with this header
|
||||
list = new LibraryList();
|
||||
list.addFirst(lib);
|
||||
importToLibraryTable.put(header, list);
|
||||
} else {
|
||||
UserLibrary old = list.peekFirst();
|
||||
boolean useThisLib = true;
|
||||
// This is the case where 2 libraries have a .h header
|
||||
// with the same name. We must decide which library to
|
||||
// use when a sketch has #include "name.h"
|
||||
@ -737,61 +841,84 @@ 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());
|
||||
//System.out.println(" old = " + oldName + " -> " + old.getInstalledFolder().getPath());
|
||||
//System.out.println(" new = " + libName + " -> " + lib.getInstalledFolder().getPath());
|
||||
String name_lc = name.toLowerCase();
|
||||
String oldName_lc = oldName.toLowerCase();
|
||||
String libName_lc = libName.toLowerCase();
|
||||
// always favor a perfect name match
|
||||
if (libName.equals(name)) {
|
||||
} else if (oldName.equals(name)) {
|
||||
continue;
|
||||
useThisLib = false;
|
||||
// check for "-master" appended (zip file from github)
|
||||
} else if (libName.equals(name+"-master")) {
|
||||
} else if (oldName.equals(name+"-master")) {
|
||||
continue;
|
||||
useThisLib = false;
|
||||
// next, favor a match with other stuff appended
|
||||
} else if (libName.startsWith(name)) {
|
||||
} else if (oldName.startsWith(name)) {
|
||||
continue;
|
||||
useThisLib = false;
|
||||
// otherwise, favor a match with stuff prepended
|
||||
} else if (libName.endsWith(name)) {
|
||||
} else if (oldName.endsWith(name)) {
|
||||
continue;
|
||||
useThisLib = false;
|
||||
// as a last resort, match if stuff prepended and appended
|
||||
} else if (libName.contains(name)) {
|
||||
} else if (oldName.contains(name)) {
|
||||
continue;
|
||||
useThisLib = false;
|
||||
// repeat all the above tests, with case insensitive matching
|
||||
} else if (libName_lc.equals(name_lc)) {
|
||||
} else if (oldName_lc.equals(name_lc)) {
|
||||
continue;
|
||||
useThisLib = false;
|
||||
} else if (libName_lc.equals(name_lc+"-master")) {
|
||||
} else if (oldName_lc.equals(name_lc+"-master")) {
|
||||
continue;
|
||||
useThisLib = false;
|
||||
} else if (libName_lc.startsWith(name_lc)) {
|
||||
} else if (oldName_lc.startsWith(name_lc)) {
|
||||
continue;
|
||||
useThisLib = false;
|
||||
} else if (libName_lc.endsWith(name_lc)) {
|
||||
} else if (oldName_lc.endsWith(name_lc)) {
|
||||
continue;
|
||||
useThisLib = false;
|
||||
} else if (libName_lc.contains(name_lc)) {
|
||||
} else if (oldName_lc.contains(name_lc)) {
|
||||
continue;
|
||||
useThisLib = false;
|
||||
} else {
|
||||
// none of these tests matched, so just default to "libName".
|
||||
}
|
||||
if (useThisLib) {
|
||||
list.addFirst(lib);
|
||||
} else {
|
||||
list.addLast(lib);
|
||||
}
|
||||
}
|
||||
importToLibraryTable.put(header, lib);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
showWarning(_("Error"), I18n
|
||||
.format("Unable to list header files in {0}", lib.getSrcFolder()), e);
|
||||
}
|
||||
}
|
||||
// repeat for ALL libraries, to pick up duplicates not visible normally.
|
||||
// any new libraries found here are NEVER used, but they are added to the
|
||||
// end of already-found headers, to allow Compiler to report them if
|
||||
// the sketch tries to use them.
|
||||
for (UserLibrary lib : librariesIndexer.getInstalledLibrariesWithDuplicates()) {
|
||||
try {
|
||||
String headers[] = headerListFromIncludePath(lib.getSrcFolder());
|
||||
for (String header : headers) {
|
||||
LibraryList list = importToLibraryTable.get(header);
|
||||
if (list != null) {
|
||||
if (!(list.hasLibrary(lib))) {
|
||||
list.addLast(lib);
|
||||
//System.out.println(" duplicate lib: " + lib.getInstalledFolder().getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public void initParameters(String args[]) {
|
||||
@ -926,49 +1053,6 @@ public class BaseNoGui {
|
||||
}
|
||||
}
|
||||
|
||||
static public void scanAndUpdateLibraries(List<File> folders) throws IOException {
|
||||
libraries = scanLibraries(folders);
|
||||
}
|
||||
|
||||
static public LibraryList scanLibraries(List<File> 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;
|
||||
}
|
||||
|
||||
static public void selectBoard(TargetBoard targetBoard) {
|
||||
TargetPlatform targetPlatform = targetBoard.getContainerPlatform();
|
||||
TargetPackage targetPackage = targetPlatform.getContainerPackage();
|
||||
|
@ -24,11 +24,11 @@ public class I18n {
|
||||
|
||||
// prompt text stuff
|
||||
|
||||
static String PROMPT_YES;
|
||||
static String PROMPT_NO;
|
||||
static String PROMPT_CANCEL;
|
||||
static String PROMPT_OK;
|
||||
static String PROMPT_BROWSE;
|
||||
public static String PROMPT_YES;
|
||||
public static String PROMPT_NO;
|
||||
public static String PROMPT_CANCEL;
|
||||
public static String PROMPT_OK;
|
||||
public static String PROMPT_BROWSE;
|
||||
|
||||
static protected void init(String language) throws MissingResourceException {
|
||||
String[] languageParts = language.split("_");
|
||||
|
@ -21,24 +21,19 @@
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
import static processing.app.I18n._;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import cc.arduino.packages.BoardPort;
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
import processing.app.debug.TargetBoard;
|
||||
import processing.app.debug.TargetPackage;
|
||||
import processing.app.debug.TargetPlatform;
|
||||
import processing.app.legacy.PConstants;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
|
||||
|
||||
/**
|
||||
* Used by Base for platform-specific tweaking, for instance finding the
|
||||
@ -75,7 +70,7 @@ public class Platform {
|
||||
}
|
||||
|
||||
|
||||
public void init() {
|
||||
public void init() throws IOException {
|
||||
}
|
||||
|
||||
|
||||
@ -169,6 +164,8 @@ public class Platform {
|
||||
}
|
||||
|
||||
public String resolveDeviceByBoardID(Map<String, TargetPackage> packages, String boardId) {
|
||||
assert packages != null;
|
||||
assert boardId != null;
|
||||
for (TargetPackage targetPackage : packages.values()) {
|
||||
for (TargetPlatform targetPlatform : targetPackage.getPlatforms().values()) {
|
||||
for (TargetBoard board : targetPlatform.getBoards().values()) {
|
||||
@ -183,33 +180,6 @@ public class Platform {
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
public interface CLibrary extends Library {
|
||||
CLibrary INSTANCE = (CLibrary)Native.loadLibrary("c", CLibrary.class);
|
||||
int setenv(String name, String value, int overwrite);
|
||||
String getenv(String name);
|
||||
int unsetenv(String name);
|
||||
int putenv(String string);
|
||||
}
|
||||
|
||||
|
||||
public void setenv(String variable, String value) {
|
||||
CLibrary clib = CLibrary.INSTANCE;
|
||||
clib.setenv(variable, value, 1);
|
||||
}
|
||||
|
||||
|
||||
public String getenv(String variable) {
|
||||
CLibrary clib = CLibrary.INSTANCE;
|
||||
return clib.getenv(variable);
|
||||
}
|
||||
|
||||
|
||||
public int unsetenv(String variable) {
|
||||
CLibrary clib = CLibrary.INSTANCE;
|
||||
return clib.unsetenv(variable);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return PConstants.platformNames[PConstants.OTHER];
|
||||
}
|
||||
@ -227,4 +197,39 @@ public class Platform {
|
||||
public List<BoardPort> filterPorts(List<BoardPort> ports, boolean aBoolean) {
|
||||
return new LinkedList<BoardPort>(ports);
|
||||
}
|
||||
|
||||
public void fixPrefsFilePermissions(File prefsFile) throws IOException, InterruptedException {
|
||||
Process process = Runtime.getRuntime().exec(new String[]{"chmod", "600", prefsFile.getAbsolutePath()}, null, null);
|
||||
process.waitFor();
|
||||
}
|
||||
|
||||
public List<File> postInstallScripts(File folder) {
|
||||
List<File> scripts = new LinkedList<File>();
|
||||
scripts.add(new File(folder, "install_script.sh"));
|
||||
scripts.add(new File(folder, "post_install.sh"));
|
||||
return scripts;
|
||||
}
|
||||
|
||||
public String getOsName() {
|
||||
return System.getProperty("os.name");
|
||||
}
|
||||
|
||||
public String getOsArch() {
|
||||
return System.getProperty("os.arch");
|
||||
}
|
||||
|
||||
public void symlink(String something, File somewhere) throws IOException, InterruptedException {
|
||||
Process process = Runtime.getRuntime().exec(new String[]{"ln", "-s", something, somewhere.getAbsolutePath()}, null, somewhere.getParentFile());
|
||||
process.waitFor();
|
||||
}
|
||||
|
||||
public void link(File something, File somewhere) throws IOException, InterruptedException {
|
||||
Process process = Runtime.getRuntime().exec(new String[]{"ln", something.getAbsolutePath(), somewhere.getAbsolutePath()}, null, null);
|
||||
process.waitFor();
|
||||
}
|
||||
|
||||
public void chmod(File file, int mode) throws IOException, InterruptedException {
|
||||
Process process = Runtime.getRuntime().exec(new String[]{"chmod", Integer.toOctalString(mode), file.getAbsolutePath()}, null, null);
|
||||
process.waitFor();
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package processing.app;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -9,8 +10,10 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.MissingResourceException;
|
||||
|
||||
import processing.app.helpers.PreferencesHelper;
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
import processing.app.legacy.PApplet;
|
||||
import processing.app.legacy.PConstants;
|
||||
@ -18,7 +21,7 @@ import processing.app.legacy.PConstants;
|
||||
|
||||
public class PreferencesData {
|
||||
|
||||
static final String PREFS_FILE = "preferences.txt";
|
||||
private static final String PREFS_FILE = "preferences.txt";
|
||||
|
||||
// data model
|
||||
|
||||
@ -29,18 +32,25 @@ public class PreferencesData {
|
||||
|
||||
|
||||
static public void init(File file) {
|
||||
if (file != null)
|
||||
if (file != null) {
|
||||
preferencesFile = file;
|
||||
else
|
||||
} else {
|
||||
preferencesFile = BaseNoGui.getSettingsFile(PREFS_FILE);
|
||||
}
|
||||
|
||||
try {
|
||||
BaseNoGui.getPlatform().fixPrefsFilePermissions(preferencesFile);
|
||||
} catch (Exception e) {
|
||||
//ignore
|
||||
}
|
||||
|
||||
// start by loading the defaults, in case something
|
||||
// important was deleted from the user prefs
|
||||
try {
|
||||
prefs.load(BaseNoGui.getLibStream("preferences.txt"));
|
||||
prefs.load(new File(BaseNoGui.getContentFile("lib"), PREFS_FILE));
|
||||
} catch (IOException e) {
|
||||
BaseNoGui.showError(null, _("Could not read default settings.\n" +
|
||||
"You'll need to reinstall Arduino."), e);
|
||||
"You'll need to reinstall Arduino."), e);
|
||||
}
|
||||
|
||||
// set some runtime constants (not saved on preferences file)
|
||||
@ -78,6 +88,10 @@ public class PreferencesData {
|
||||
fixPreferences();
|
||||
}
|
||||
|
||||
public static File getPreferencesFile() {
|
||||
return preferencesFile;
|
||||
}
|
||||
|
||||
private static void fixPreferences() {
|
||||
String baud = get("serial.debug_rate");
|
||||
if ("14400".equals(baud) || "28800".equals(baud)) {
|
||||
@ -86,41 +100,6 @@ public class PreferencesData {
|
||||
}
|
||||
|
||||
|
||||
static public String[] loadStrings(InputStream input) {
|
||||
try {
|
||||
BufferedReader reader =
|
||||
new BufferedReader(new InputStreamReader(input, "UTF-8"));
|
||||
|
||||
String lines[] = new String[100];
|
||||
int lineCount = 0;
|
||||
String line = null;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (lineCount == lines.length) {
|
||||
String temp[] = new String[lineCount << 1];
|
||||
System.arraycopy(lines, 0, temp, 0, lineCount);
|
||||
lines = temp;
|
||||
}
|
||||
lines[lineCount++] = line;
|
||||
}
|
||||
reader.close();
|
||||
|
||||
if (lineCount == lines.length) {
|
||||
return lines;
|
||||
}
|
||||
|
||||
// resize array to appropriate amount for these lines
|
||||
String output[] = new String[lineCount];
|
||||
System.arraycopy(lines, 0, output, 0, lineCount);
|
||||
return output;
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
//throw new RuntimeException("Error inside loadStrings()");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
static protected void save() {
|
||||
if (!doSave)
|
||||
return;
|
||||
@ -131,18 +110,30 @@ public class PreferencesData {
|
||||
if (preferencesFile == null) return;
|
||||
|
||||
// Fix for 0163 to properly use Unicode when writing preferences.txt
|
||||
PrintWriter writer = PApplet.createWriter(preferencesFile);
|
||||
PrintWriter writer = null;
|
||||
try {
|
||||
writer = PApplet.createWriter(preferencesFile);
|
||||
|
||||
String[] keys = prefs.keySet().toArray(new String[0]);
|
||||
Arrays.sort(keys);
|
||||
for (String key: keys) {
|
||||
if (key.startsWith("runtime."))
|
||||
continue;
|
||||
writer.println(key + "=" + prefs.get(key));
|
||||
String[] keys = prefs.keySet().toArray(new String[0]);
|
||||
Arrays.sort(keys);
|
||||
for (String key : keys) {
|
||||
if (key.startsWith("runtime."))
|
||||
continue;
|
||||
writer.println(key + "=" + prefs.get(key));
|
||||
}
|
||||
|
||||
writer.flush();
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
writer.flush();
|
||||
writer.close();
|
||||
try {
|
||||
BaseNoGui.getPlatform().fixPrefsFilePermissions(preferencesFile);
|
||||
} catch (Exception e) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -194,6 +185,13 @@ public class PreferencesData {
|
||||
return Integer.parseInt(get(attribute));
|
||||
}
|
||||
|
||||
static public int getInteger(String attribute, int defaultValue) {
|
||||
if (has(attribute)) {
|
||||
return getInteger(attribute);
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
static public void setInteger(String key, int value) {
|
||||
set(key, String.valueOf(value));
|
||||
@ -205,10 +203,27 @@ public class PreferencesData {
|
||||
return new PreferencesMap(prefs);
|
||||
}
|
||||
|
||||
static public void removeAllKeysWithPrefix(String prefix) {
|
||||
Iterator<String> keys = prefs.keySet().iterator();
|
||||
while (keys.hasNext())
|
||||
if (keys.next().startsWith(prefix))
|
||||
keys.remove();
|
||||
}
|
||||
|
||||
// Decide wether changed preferences will be saved. When value is
|
||||
// false, Preferences.save becomes a no-op.
|
||||
static public void setDoSave(boolean value)
|
||||
{
|
||||
doSave = value;
|
||||
}
|
||||
|
||||
static public Font getFont(String attr) {
|
||||
Font font = PreferencesHelper.getFont(prefs, attr);
|
||||
if (font == null) {
|
||||
String value = defaults.get(attr);
|
||||
prefs.put(attr, value);
|
||||
font = PreferencesHelper.getFont(prefs, attr);
|
||||
}
|
||||
return font;
|
||||
}
|
||||
}
|
||||
|
@ -88,11 +88,12 @@ public class Serial implements SerialPortEventListener {
|
||||
BaseNoGui.getBoardPreferences().get("serial.disableDTR") == null);
|
||||
}
|
||||
|
||||
public static boolean touchPort(String iname, int irate) throws SerialException {
|
||||
public static boolean touchForCDCReset(String iname) throws SerialException {
|
||||
SerialPort serialPort = new SerialPort(iname);
|
||||
try {
|
||||
serialPort.openPort();
|
||||
serialPort.setParams(irate, 8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
|
||||
serialPort.setParams(1200, 8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
|
||||
serialPort.setDTR(false);
|
||||
serialPort.closePort();
|
||||
return true;
|
||||
} catch (SerialPortException e) {
|
||||
|
@ -25,13 +25,7 @@ package processing.app.debug;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@ -45,6 +39,9 @@ import cc.arduino.packages.BoardPort;
|
||||
import cc.arduino.packages.Uploader;
|
||||
import cc.arduino.packages.UploaderFactory;
|
||||
|
||||
import org.apache.commons.exec.CommandLine;
|
||||
import org.apache.commons.exec.DefaultExecutor;
|
||||
import org.apache.commons.exec.ExecuteStreamHandler;
|
||||
import processing.app.BaseNoGui;
|
||||
import processing.app.I18n;
|
||||
import processing.app.PreferencesData;
|
||||
@ -52,10 +49,12 @@ 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;
|
||||
import processing.app.tools.DoubleQuotedArgumentsOnWindowsCommandLine;
|
||||
|
||||
public class Compiler implements MessageConsumer {
|
||||
|
||||
@ -68,6 +67,7 @@ public class Compiler implements MessageConsumer {
|
||||
private SketchData sketch;
|
||||
private PreferencesMap prefs;
|
||||
private boolean verbose;
|
||||
private boolean saveHex;
|
||||
|
||||
private List<File> objectFiles;
|
||||
|
||||
@ -84,7 +84,7 @@ public class Compiler implements MessageConsumer {
|
||||
|
||||
private ProgressListener progressListener;
|
||||
|
||||
static public String build(SketchData data, String buildPath, File tempBuildFolder, ProgressListener progListener, boolean verbose) throws RunnerException, PreferencesMapException {
|
||||
static public String build(SketchData data, String buildPath, File tempBuildFolder, ProgressListener progListener, boolean verbose, boolean save) throws RunnerException, PreferencesMapException {
|
||||
if (SketchData.checkSketchFile(data.getPrimaryFile()) == null)
|
||||
BaseNoGui.showError(_("Bad file selected"),
|
||||
_("Bad sketch primary file or bad sketch directory structure"), null);
|
||||
@ -113,9 +113,16 @@ public class Compiler implements MessageConsumer {
|
||||
|
||||
// compile the program. errors will happen as a RunnerException
|
||||
// that will bubble up to whomever called build().
|
||||
if (compiler.compile(verbose)) {
|
||||
compiler.size(compiler.getBuildPreferences());
|
||||
return primaryClassName;
|
||||
try {
|
||||
if (compiler.compile(verbose, save)) {
|
||||
compiler.size(compiler.getBuildPreferences());
|
||||
return primaryClassName;
|
||||
}
|
||||
} catch (RunnerException e) {
|
||||
// when the compile fails, take this opportunity to show
|
||||
// any helpful info possible before throwing the exception
|
||||
compiler.adviseDuplicateLibraries();
|
||||
throw e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -183,6 +190,9 @@ public class Compiler implements MessageConsumer {
|
||||
sketch = _sketch;
|
||||
prefs = createBuildPreferences(_buildPath, _primaryClassName);
|
||||
|
||||
// provide access to the source tree
|
||||
prefs.put("build.source.path", _sketch.getFolder().getAbsolutePath());
|
||||
|
||||
// Start with an empty progress listener
|
||||
progressListener = new ProgressListener() {
|
||||
@Override
|
||||
@ -311,10 +321,10 @@ public class Compiler implements MessageConsumer {
|
||||
if (maxDataSize > 0) {
|
||||
System.out
|
||||
.println(I18n
|
||||
.format(
|
||||
_("Global variables use {0} bytes ({2}%%) of dynamic memory, leaving {3} bytes for local variables. Maximum is {1} bytes."),
|
||||
dataSize, maxDataSize, dataSize * 100 / maxDataSize,
|
||||
maxDataSize - dataSize));
|
||||
.format(
|
||||
_("Global variables use {0} bytes ({2}%%) of dynamic memory, leaving {3} bytes for local variables. Maximum is {1} bytes."),
|
||||
dataSize, maxDataSize, dataSize * 100 / maxDataSize,
|
||||
maxDataSize - dataSize));
|
||||
} else {
|
||||
System.out.println(I18n
|
||||
.format(_("Global variables use {0} bytes of dynamic memory."), dataSize));
|
||||
@ -341,11 +351,16 @@ public class Compiler implements MessageConsumer {
|
||||
* @return true if successful.
|
||||
* @throws RunnerException Only if there's a problem. Only then.
|
||||
*/
|
||||
public boolean compile(boolean _verbose) throws RunnerException, PreferencesMapException {
|
||||
public boolean compile(boolean _verbose, boolean _save) throws RunnerException, PreferencesMapException {
|
||||
preprocess(prefs.get("build.path"));
|
||||
|
||||
verbose = _verbose || PreferencesData.getBoolean("build.verbose");
|
||||
saveHex = _save;
|
||||
sketchIsCompiled = false;
|
||||
|
||||
// Hook runs at Start of Compilation
|
||||
runActions("hooks.prebuild", prefs);
|
||||
|
||||
objectFiles = new ArrayList<File>();
|
||||
|
||||
// 0. include paths for core + all libraries
|
||||
@ -354,11 +369,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)
|
||||
@ -370,7 +389,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} "
|
||||
@ -382,26 +401,26 @@ public class Compiler implements MessageConsumer {
|
||||
}
|
||||
|
||||
// 1. compile the sketch (already in the buildPath)
|
||||
progressListener.progress(30);
|
||||
progressListener.progress(20);
|
||||
compileSketch(includeFolders);
|
||||
sketchIsCompiled = true;
|
||||
|
||||
// 2. compile the libraries, outputting .o files to: <buildPath>/<library>/
|
||||
// Doesn't really use configPreferences
|
||||
progressListener.progress(40);
|
||||
progressListener.progress(30);
|
||||
compileLibraries(includeFolders);
|
||||
|
||||
// 3. compile the core, outputting .o files to <buildPath> and then
|
||||
// collecting them into the core.a library file.
|
||||
progressListener.progress(50);
|
||||
progressListener.progress(40);
|
||||
compileCore();
|
||||
|
||||
// 4. link it all together into the .elf file
|
||||
progressListener.progress(60);
|
||||
progressListener.progress(50);
|
||||
compileLink();
|
||||
|
||||
// 5. run objcopy to generate output files
|
||||
progressListener.progress(75);
|
||||
progressListener.progress(60);
|
||||
List<String> objcopyPatterns = new ArrayList<String>();
|
||||
for (String key : prefs.keySet()) {
|
||||
if (key.startsWith("recipe.objcopy.") && key.endsWith(".pattern"))
|
||||
@ -412,10 +431,39 @@ public class Compiler implements MessageConsumer {
|
||||
runRecipe(recipe);
|
||||
}
|
||||
|
||||
// 7. save the hex file
|
||||
if (saveHex) {
|
||||
progressListener.progress(80);
|
||||
saveHex();
|
||||
}
|
||||
|
||||
progressListener.progress(90);
|
||||
|
||||
// Hook runs at End of Compilation
|
||||
runActions("hooks.postbuild", prefs);
|
||||
adviseDuplicateLibraries();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void adviseDuplicateLibraries() {
|
||||
for (int i=0; i < importedDuplicateHeaders.size(); i++) {
|
||||
System.out.println(I18n.format(_("Multiple libraries were found for \"{0}\""),
|
||||
importedDuplicateHeaders.get(i)));
|
||||
boolean first = true;
|
||||
for (UserLibrary lib : importedDuplicateLibraries.get(i)) {
|
||||
if (first) {
|
||||
System.out.println(I18n.format(_(" Used: {0}"),
|
||||
lib.getInstalledFolder().getPath()));
|
||||
first = false;
|
||||
} else {
|
||||
System.out.println(I18n.format(_(" Not used: {0}"),
|
||||
lib.getInstalledFolder().getPath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private PreferencesMap createBuildPreferences(String _buildPath,
|
||||
String _primaryClassName)
|
||||
throws RunnerException {
|
||||
@ -647,7 +695,6 @@ public class Compiler implements MessageConsumer {
|
||||
command = stringList.toArray(new String[stringList.size()]);
|
||||
if (command.length == 0)
|
||||
return;
|
||||
int result = 0;
|
||||
|
||||
if (verbose) {
|
||||
for (String c : command)
|
||||
@ -655,30 +702,57 @@ public class Compiler implements MessageConsumer {
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
Process process;
|
||||
DefaultExecutor executor = new DefaultExecutor();
|
||||
executor.setStreamHandler(new ExecuteStreamHandler() {
|
||||
@Override
|
||||
public void setProcessInputStream(OutputStream os) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProcessErrorStream(InputStream is) throws IOException {
|
||||
forwardToMessage(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProcessOutputStream(InputStream is) throws IOException {
|
||||
forwardToMessage(is);
|
||||
}
|
||||
|
||||
private void forwardToMessage(InputStream is) throws IOException {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
message(line + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
CommandLine commandLine = new DoubleQuotedArgumentsOnWindowsCommandLine(command[0]);
|
||||
for (int i = 1; i < command.length; i++) {
|
||||
commandLine.addArgument(command[i], false);
|
||||
}
|
||||
|
||||
int result;
|
||||
executor.setExitValues(null);
|
||||
try {
|
||||
process = ProcessUtils.exec(command);
|
||||
result = executor.execute(commandLine);
|
||||
} catch (IOException e) {
|
||||
RunnerException re = new RunnerException(e.getMessage());
|
||||
re.hideStackTrace();
|
||||
throw re;
|
||||
}
|
||||
|
||||
MessageSiphon in = new MessageSiphon(process.getInputStream(), this);
|
||||
MessageSiphon err = new MessageSiphon(process.getErrorStream(), this);
|
||||
|
||||
// wait for the process to finish. if interrupted
|
||||
// before waitFor returns, continue waiting
|
||||
boolean compiling = true;
|
||||
while (compiling) {
|
||||
try {
|
||||
in.join();
|
||||
err.join();
|
||||
result = process.waitFor();
|
||||
//System.out.println("result is " + result);
|
||||
compiling = false;
|
||||
} catch (InterruptedException ignored) { }
|
||||
}
|
||||
executor.setExitValues(new int[0]);
|
||||
|
||||
// an error was queued up by message(), barf this back to compile(),
|
||||
// which will barf it back to Editor. if you're having trouble
|
||||
@ -720,10 +794,10 @@ public class Compiler implements MessageConsumer {
|
||||
s = s.substring(0, i) + s.substring(i + (buildPath + File.separator).length());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// look for error line, which contains file name, line number,
|
||||
// and at least the first line of the error message
|
||||
String errorFormat = "([\\w\\d_]+.\\w+):(\\d+):\\s*error:\\s*(.*)\\s*";
|
||||
String errorFormat = "(.+\\.\\w+):(\\d+)(:\\d+)*:\\s*error:\\s*(.*)\\s*";
|
||||
String[] pieces = PApplet.match(s, errorFormat);
|
||||
|
||||
// if (pieces != null && exception == null) {
|
||||
@ -732,56 +806,56 @@ public class Compiler implements MessageConsumer {
|
||||
// }
|
||||
|
||||
if (pieces != null) {
|
||||
String error = pieces[3], msg = "";
|
||||
String error = pieces[pieces.length - 1], msg = "";
|
||||
|
||||
if (pieces[3].trim().equals("SPI.h: No such file or directory")) {
|
||||
if (error.trim().equals("SPI.h: No such file or directory")) {
|
||||
error = _("Please import the SPI library from the Sketch > Import Library menu.");
|
||||
msg = _("\nAs of Arduino 0019, the Ethernet library depends on the SPI library." +
|
||||
"\nYou appear to be using it or another library that depends on the SPI library.\n\n");
|
||||
}
|
||||
|
||||
if (pieces[3].trim().equals("'BYTE' was not declared in this scope")) {
|
||||
if (error.trim().equals("'BYTE' was not declared in this scope")) {
|
||||
error = _("The 'BYTE' keyword is no longer supported.");
|
||||
msg = _("\nAs of Arduino 1.0, the 'BYTE' keyword is no longer supported." +
|
||||
"\nPlease use Serial.write() instead.\n\n");
|
||||
}
|
||||
|
||||
if (pieces[3].trim().equals("no matching function for call to 'Server::Server(int)'")) {
|
||||
if (error.trim().equals("no matching function for call to 'Server::Server(int)'")) {
|
||||
error = _("The Server class has been renamed EthernetServer.");
|
||||
msg = _("\nAs of Arduino 1.0, the Server class in the Ethernet library " +
|
||||
"has been renamed to EthernetServer.\n\n");
|
||||
}
|
||||
|
||||
if (pieces[3].trim().equals("no matching function for call to 'Client::Client(byte [4], int)'")) {
|
||||
if (error.trim().equals("no matching function for call to 'Client::Client(byte [4], int)'")) {
|
||||
error = _("The Client class has been renamed EthernetClient.");
|
||||
msg = _("\nAs of Arduino 1.0, the Client class in the Ethernet library " +
|
||||
"has been renamed to EthernetClient.\n\n");
|
||||
}
|
||||
|
||||
if (pieces[3].trim().equals("'Udp' was not declared in this scope")) {
|
||||
if (error.trim().equals("'Udp' was not declared in this scope")) {
|
||||
error = _("The Udp class has been renamed EthernetUdp.");
|
||||
msg = _("\nAs of Arduino 1.0, the Udp class in the Ethernet library " +
|
||||
"has been renamed to EthernetUdp.\n\n");
|
||||
}
|
||||
|
||||
if (pieces[3].trim().equals("'class TwoWire' has no member named 'send'")) {
|
||||
if (error.trim().equals("'class TwoWire' has no member named 'send'")) {
|
||||
error = _("Wire.send() has been renamed Wire.write().");
|
||||
msg = _("\nAs of Arduino 1.0, the Wire.send() function was renamed " +
|
||||
"to Wire.write() for consistency with other libraries.\n\n");
|
||||
}
|
||||
|
||||
if (pieces[3].trim().equals("'class TwoWire' has no member named 'receive'")) {
|
||||
if (error.trim().equals("'class TwoWire' has no member named 'receive'")) {
|
||||
error = _("Wire.receive() has been renamed Wire.read().");
|
||||
msg = _("\nAs of Arduino 1.0, the Wire.receive() function was renamed " +
|
||||
"to Wire.read() for consistency with other libraries.\n\n");
|
||||
}
|
||||
|
||||
if (pieces[3].trim().equals("'Mouse' was not declared in this scope")) {
|
||||
if (error.trim().equals("'Mouse' was not declared in this scope")) {
|
||||
error = _("'Mouse' only supported on the Arduino Leonardo");
|
||||
//msg = _("\nThe 'Mouse' class is only supported on the Arduino Leonardo.\n\n");
|
||||
}
|
||||
|
||||
if (pieces[3].trim().equals("'Keyboard' was not declared in this scope")) {
|
||||
if (error.trim().equals("'Keyboard' was not declared in this scope")) {
|
||||
error = _("'Keyboard' only supported on the Arduino Leonardo");
|
||||
//msg = _("\nThe 'Keyboard' class is only supported on the Arduino Leonardo.\n\n");
|
||||
}
|
||||
@ -799,13 +873,15 @@ public class Compiler implements MessageConsumer {
|
||||
SketchCode code = sketch.getCode(e.getCodeIndex());
|
||||
String fileName = (code.isExtension("ino") || code.isExtension("pde")) ? code.getPrettyName() : code.getFileName();
|
||||
int lineNum = e.getCodeLine() + 1;
|
||||
s = fileName + ":" + lineNum + ": error: " + pieces[3] + msg;
|
||||
s = fileName + ":" + lineNum + ": error: " + error + msg;
|
||||
}
|
||||
|
||||
if (e != null) {
|
||||
if (exception == null || exception.getMessage().equals(e.getMessage())) {
|
||||
exception = e;
|
||||
exception.hideStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (exception == null && e != null) {
|
||||
exception = e;
|
||||
exception.hideStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (s.contains("undefined reference to `SPIClass::begin()'") &&
|
||||
@ -831,6 +907,8 @@ public class Compiler implements MessageConsumer {
|
||||
dict.put("source_file", sourceFile.getAbsolutePath());
|
||||
dict.put("object_file", objectFile.getAbsolutePath());
|
||||
|
||||
setupWarningFlags(dict);
|
||||
|
||||
String cmd = prefs.getOrExcept(recipe);
|
||||
try {
|
||||
return StringReplacer.formatAndSplit(cmd, dict, true);
|
||||
@ -839,6 +917,19 @@ public class Compiler implements MessageConsumer {
|
||||
}
|
||||
}
|
||||
|
||||
private void setupWarningFlags(PreferencesMap dict) {
|
||||
if (dict.containsKey("compiler.warning_level")) {
|
||||
String key = "compiler.warning_flags." + dict.get("compiler.warning_level");
|
||||
dict.put("compiler.warning_flags", dict.get(key));
|
||||
} else {
|
||||
dict.put("compiler.warning_flags", dict.get("compiler.warning_flags.none"));
|
||||
}
|
||||
|
||||
if (dict.get("compiler.warning_flags") == null) {
|
||||
dict.remove("compiler.warning_flags");
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void createFolder(File folder) throws RunnerException {
|
||||
@ -886,21 +977,21 @@ public class Compiler implements MessageConsumer {
|
||||
// 2. compile the libraries, outputting .o files to:
|
||||
// <buildPath>/<library>/
|
||||
void compileLibraries(List<File> includeFolders) throws RunnerException, PreferencesMapException {
|
||||
for (Library lib : importedLibraries) {
|
||||
for (UserLibrary lib : importedLibraries) {
|
||||
compileLibrary(lib, includeFolders);
|
||||
}
|
||||
}
|
||||
|
||||
private void compileLibrary(Library lib, List<File> includeFolders)
|
||||
private void compileLibrary(UserLibrary lib, List<File> 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
|
||||
@ -908,11 +999,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);
|
||||
}
|
||||
@ -1031,6 +1122,8 @@ public class Compiler implements MessageConsumer {
|
||||
dict.put("object_files", objectFileList);
|
||||
dict.put("ide_version", "" + BaseNoGui.REVISION);
|
||||
|
||||
setupWarningFlags(dict);
|
||||
|
||||
String[] cmdArray;
|
||||
String cmd = prefs.getOrExcept("recipe.c.combine.pattern");
|
||||
try {
|
||||
@ -1041,6 +1134,18 @@ public class Compiler implements MessageConsumer {
|
||||
execAsynchronously(cmdArray);
|
||||
}
|
||||
|
||||
void runActions(String recipeClass, PreferencesMap prefs) throws RunnerException, PreferencesMapException {
|
||||
List<String> patterns = new ArrayList<String>();
|
||||
for (String key : prefs.keySet()) {
|
||||
if (key.startsWith("recipe."+recipeClass) && key.endsWith(".pattern"))
|
||||
patterns.add(key);
|
||||
}
|
||||
Collections.sort(patterns);
|
||||
for (String recipe : patterns) {
|
||||
runRecipe(recipe);
|
||||
}
|
||||
}
|
||||
|
||||
void runRecipe(String recipe) throws RunnerException, PreferencesMapException {
|
||||
PreferencesMap dict = new PreferencesMap(prefs);
|
||||
dict.put("ide_version", "" + BaseNoGui.REVISION);
|
||||
@ -1054,6 +1159,32 @@ public class Compiler implements MessageConsumer {
|
||||
}
|
||||
execAsynchronously(cmdArray);
|
||||
}
|
||||
|
||||
//7. Save the .hex file
|
||||
void saveHex() throws RunnerException {
|
||||
if (!prefs.containsKey("recipe.output.tmp_file") || !prefs.containsKey("recipe.output.save_file")) {
|
||||
System.err.println(_("Warning: This core does not support exporting sketches. Please consider upgrading it or contacting its author"));
|
||||
return;
|
||||
}
|
||||
|
||||
PreferencesMap dict = new PreferencesMap(prefs);
|
||||
dict.put("ide_version", "" + BaseNoGui.REVISION);
|
||||
|
||||
try {
|
||||
String compiledSketch = prefs.getOrExcept("recipe.output.tmp_file");
|
||||
compiledSketch = StringReplacer.replaceFromMapping(compiledSketch, dict);
|
||||
String copyOfCompiledSketch = prefs.getOrExcept("recipe.output.save_file");
|
||||
copyOfCompiledSketch = StringReplacer.replaceFromMapping(copyOfCompiledSketch, dict);
|
||||
|
||||
File compiledSketchFile = new File(prefs.get("build.path"), compiledSketch);
|
||||
File copyOfCompiledSketchFile = new File(sketch.getFolder(), copyOfCompiledSketch);
|
||||
|
||||
FileUtils.copyFile(compiledSketchFile, copyOfCompiledSketchFile);
|
||||
} catch (Exception e) {
|
||||
throw new RunnerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String prepareIncludes(List<File> includeFolders) {
|
||||
String res = "";
|
||||
@ -1120,12 +1251,12 @@ public class Compiler implements MessageConsumer {
|
||||
// 2. run preproc on that code using the sugg class name
|
||||
// to create a single .java file and write to buildpath
|
||||
|
||||
FileOutputStream outputStream = null;
|
||||
try {
|
||||
// Output file
|
||||
File streamFile = new File(buildPath, sketch.getName() + ".cpp");
|
||||
FileOutputStream outputStream = new FileOutputStream(streamFile);
|
||||
outputStream = new FileOutputStream(streamFile);
|
||||
preprocessor.write(outputStream);
|
||||
outputStream.close();
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
fnfe.printStackTrace();
|
||||
String msg = _("Build folder disappeared or could not be written");
|
||||
@ -1140,15 +1271,32 @@ public class Compiler implements MessageConsumer {
|
||||
System.err.println(I18n.format(_("Uncaught exception type: {0}"), ex.getClass()));
|
||||
ex.printStackTrace();
|
||||
throw new RunnerException(ex.toString());
|
||||
} finally {
|
||||
if (outputStream != null) {
|
||||
try {
|
||||
outputStream.close();
|
||||
} catch (IOException e) {
|
||||
//noop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// grab the imports from the code just preproc'd
|
||||
|
||||
importedLibraries = new LibraryList();
|
||||
importedDuplicateHeaders = new ArrayList<String>();
|
||||
importedDuplicateLibraries = new ArrayList<LibraryList>();
|
||||
for (String item : preprocessor.getExtraImports()) {
|
||||
Library lib = BaseNoGui.importToLibraryTable.get(item);
|
||||
if (lib != null && !importedLibraries.contains(lib)) {
|
||||
importedLibraries.add(lib);
|
||||
LibraryList list = BaseNoGui.importToLibraryTable.get(item);
|
||||
if (list != null) {
|
||||
UserLibrary lib = list.peekFirst();
|
||||
if (lib != null && !importedLibraries.contains(lib)) {
|
||||
importedLibraries.add(lib);
|
||||
if (list.size() > 1) {
|
||||
importedDuplicateHeaders.add(item);
|
||||
importedDuplicateLibraries.add(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1180,6 +1328,8 @@ public class Compiler implements MessageConsumer {
|
||||
* List of library folders.
|
||||
*/
|
||||
private LibraryList importedLibraries;
|
||||
private List<String> importedDuplicateHeaders;
|
||||
private List<LibraryList> importedDuplicateLibraries;
|
||||
|
||||
/**
|
||||
* Map an error from a set of processed .java files back to its location
|
||||
|
113
arduino-core/src/processing/app/debug/LegacyTargetBoard.java
Normal file
113
arduino-core/src/processing/app/debug/LegacyTargetBoard.java
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
TargetPackage - Represents a hardware package
|
||||
Part of the Arduino project - http://www.arduino.cc/
|
||||
|
||||
Copyright (c) 2014 Cristian Maglie
|
||||
|
||||
This program 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
package processing.app.debug;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
import static processing.app.I18n.format;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
|
||||
public class LegacyTargetBoard implements TargetBoard {
|
||||
|
||||
private String id;
|
||||
private PreferencesMap prefs;
|
||||
private Map<String, PreferencesMap> menuOptions = new LinkedHashMap<String, PreferencesMap>();
|
||||
private TargetPlatform containerPlatform;
|
||||
|
||||
/**
|
||||
* Create a TargetBoard based on preferences passed as argument.
|
||||
*
|
||||
* @param _prefs
|
||||
* @return
|
||||
*/
|
||||
public LegacyTargetBoard(String _id, PreferencesMap _prefs,
|
||||
TargetPlatform parent) {
|
||||
containerPlatform = parent;
|
||||
id = _id;
|
||||
prefs = new PreferencesMap(_prefs);
|
||||
|
||||
// Setup sub-menus
|
||||
PreferencesMap menus = prefs.firstLevelMap().get("menu");
|
||||
if (menus != null)
|
||||
menuOptions = menus.firstLevelMap();
|
||||
|
||||
// Auto generate build.board if not set
|
||||
if (!prefs.containsKey("build.board")) {
|
||||
String board = containerPlatform.getId() + "_" + id;
|
||||
board = board.toUpperCase();
|
||||
prefs.put("build.board", board);
|
||||
System.out
|
||||
.println(format(_("Board {0}:{1}:{2} doesn''t define a ''build.board'' preference. Auto-set to: {3}"),
|
||||
containerPlatform.getContainerPackage().getId(),
|
||||
containerPlatform.getId(), id, board));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return prefs.get("name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferencesMap getPreferences() {
|
||||
return prefs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMenu(String menuId) {
|
||||
return menuOptions.containsKey(menuId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferencesMap getMenuLabels(String menuId) {
|
||||
return menuOptions.get(menuId).topLevelMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMenuLabel(String menuId, String selectionId) {
|
||||
return getMenuLabels(menuId).get(selectionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getMenuIds() {
|
||||
return menuOptions.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferencesMap getMenuPreferences(String menuId, String selectionId) {
|
||||
return menuOptions.get(menuId).subTree(selectionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetPlatform getContainerPlatform() {
|
||||
return containerPlatform;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
TargetPackage - Represents a hardware package
|
||||
Part of the Arduino project - http://www.arduino.cc/
|
||||
|
||||
Copyright (c) 2011 Cristian Maglie
|
||||
|
||||
This program 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
package processing.app.debug;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
import static processing.app.helpers.filefilters.OnlyDirs.ONLY_DIRS;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import processing.app.I18n;
|
||||
|
||||
public class LegacyTargetPackage implements TargetPackage {
|
||||
|
||||
private String id;
|
||||
private Map<String, TargetPlatform> platforms;
|
||||
|
||||
public LegacyTargetPackage(String _id, File _folder) throws TargetPlatformException {
|
||||
id = _id;
|
||||
platforms = new LinkedHashMap<String, TargetPlatform>();
|
||||
|
||||
File[] folders = _folder.listFiles(ONLY_DIRS);
|
||||
if (folders == null)
|
||||
return;
|
||||
|
||||
for (File subFolder : folders) {
|
||||
if (!subFolder.exists() || !subFolder.canRead())
|
||||
continue;
|
||||
String arch = subFolder.getName();
|
||||
try {
|
||||
TargetPlatform platform = new LegacyTargetPlatform(arch, subFolder, this);
|
||||
platforms.put(arch, platform);
|
||||
} catch (TargetPlatformException e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (platforms.size() == 0) {
|
||||
throw new TargetPlatformException(I18n
|
||||
.format(_("No valid hardware definitions found in folder {0}."),
|
||||
_folder.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, TargetPlatform> getPlatforms() {
|
||||
return platforms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<TargetPlatform> platforms() {
|
||||
return platforms.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetPlatform get(String platform) {
|
||||
return platforms.get(platform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPlatform(TargetPlatform platform) {
|
||||
return platforms.containsKey(platform.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
241
arduino-core/src/processing/app/debug/LegacyTargetPlatform.java
Normal file
241
arduino-core/src/processing/app/debug/LegacyTargetPlatform.java
Normal file
@ -0,0 +1,241 @@
|
||||
/*
|
||||
TargetPlatform - Represents a hardware platform
|
||||
Part of the Arduino project - http://www.arduino.cc/
|
||||
|
||||
Copyright (c) 2009-2014 Arduino
|
||||
|
||||
This program 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
package processing.app.debug;
|
||||
|
||||
import processing.app.BaseNoGui;
|
||||
import processing.app.I18n;
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
import static processing.app.I18n.format;
|
||||
|
||||
public class LegacyTargetPlatform implements TargetPlatform {
|
||||
|
||||
private String id;
|
||||
private File folder;
|
||||
|
||||
private TargetPackage containerPackage;
|
||||
protected PreferencesMap preferences = new PreferencesMap();
|
||||
|
||||
private Map<String, TargetBoard> boards = new LinkedHashMap<String, TargetBoard>();
|
||||
private TargetBoard defaultBoard;
|
||||
|
||||
/**
|
||||
* Contains preferences for every defined programmer
|
||||
*/
|
||||
private Map<String, PreferencesMap> programmers = new LinkedHashMap<String, PreferencesMap>();
|
||||
|
||||
/**
|
||||
* Contains labels for top level menus
|
||||
*/
|
||||
private PreferencesMap customMenus = new PreferencesMap();
|
||||
|
||||
public LegacyTargetPlatform(String _name, File _folder, TargetPackage parent)
|
||||
throws TargetPlatformException {
|
||||
|
||||
id = _name;
|
||||
folder = _folder;
|
||||
containerPackage = parent;
|
||||
|
||||
// If there is no boards.txt, this is not a valid 1.5 hardware folder
|
||||
File boardsFile = new File(folder, "boards.txt");
|
||||
if (!boardsFile.exists() || !boardsFile.canRead())
|
||||
throw new TargetPlatformException(
|
||||
format(_("Could not find boards.txt in {0}. Is it pre-1.5?"),
|
||||
folder.getAbsolutePath()));
|
||||
|
||||
// Load boards
|
||||
try {
|
||||
Map<String, PreferencesMap> boardsPreferences = new PreferencesMap(
|
||||
boardsFile).firstLevelMap();
|
||||
|
||||
// Create custom menus for this platform
|
||||
PreferencesMap menus = boardsPreferences.get("menu");
|
||||
if (menus != null)
|
||||
customMenus = menus.topLevelMap();
|
||||
boardsPreferences.remove("menu");
|
||||
|
||||
// Create boards
|
||||
Set<String> boardIds = boardsPreferences.keySet();
|
||||
for (String boardId : boardIds) {
|
||||
PreferencesMap preferences = boardsPreferences.get(boardId);
|
||||
TargetBoard board = new LegacyTargetBoard(boardId, preferences, this);
|
||||
boards.put(boardId, board);
|
||||
|
||||
// Pick the first board as default
|
||||
if (defaultBoard == null)
|
||||
defaultBoard = board;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new TargetPlatformException(format(_("Error loading {0}"),
|
||||
boardsFile.getAbsolutePath()), e);
|
||||
}
|
||||
|
||||
File platformsFile = new File(folder, "platform.txt");
|
||||
try {
|
||||
if (platformsFile.exists() && platformsFile.canRead()) {
|
||||
preferences.load(platformsFile);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new TargetPlatformException(
|
||||
format(_("Error loading {0}"), platformsFile.getAbsolutePath()), e);
|
||||
}
|
||||
|
||||
// Allow overriding values in platform.txt. This allows changing
|
||||
// platform.txt (e.g. to use a system-wide toolchain), without
|
||||
// having to modify platform.txt (which, when running from git,
|
||||
// prevents files being marked as changed).
|
||||
File localPlatformsFile = new File(folder, "platform.local.txt");
|
||||
try {
|
||||
if (localPlatformsFile.exists() && localPlatformsFile.canRead()) {
|
||||
preferences.load(localPlatformsFile);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new TargetPlatformException(
|
||||
format(_("Error loading {0}"), localPlatformsFile.getAbsolutePath()), e);
|
||||
}
|
||||
|
||||
if (!preferences.containsKey("rewriting") || !"disabled".equals(preferences.get("rewriting"))) {
|
||||
try {
|
||||
rewriteKeysOfOldPlatformsTxtAndWarnAboutIt();
|
||||
} catch (IOException e) {
|
||||
throw new TargetPlatformException(e);
|
||||
}
|
||||
}
|
||||
|
||||
File progFile = new File(folder, "programmers.txt");
|
||||
try {
|
||||
if (progFile.exists() && progFile.canRead()) {
|
||||
PreferencesMap prefs = new PreferencesMap();
|
||||
prefs.load(progFile);
|
||||
programmers = prefs.firstLevelMap();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new TargetPlatformException(format(_("Error loading {0}"),
|
||||
progFile.getAbsolutePath()), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void rewriteKeysOfOldPlatformsTxtAndWarnAboutIt() throws IOException {
|
||||
File platformRewrite = new File(BaseNoGui.getHardwareFolder(), "platform.keys.rewrite.txt");
|
||||
PreferencesMap platformRewriteProps = new PreferencesMap(platformRewrite);
|
||||
|
||||
PreferencesMap oldProps = platformRewriteProps.subTree("old");
|
||||
PreferencesMap newProps = platformRewriteProps.subTree("new");
|
||||
|
||||
String platformName = preferences.get("name");
|
||||
if (platformName == null) {
|
||||
platformName = folder.getAbsolutePath();
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> entry : oldProps.entrySet()) {
|
||||
String preferencesKey = entry.getKey().substring(entry.getKey().indexOf(".") + 1);
|
||||
if (preferences.containsKey(preferencesKey) && entry.getValue().equals(preferences.get(preferencesKey))) {
|
||||
System.err.println(I18n.format(_("Warning: platform.txt from core '{0}' contains deprecated {1}, automatically converted to {2}. Consider upgrading this core."), platformName, preferencesKey + "=" + entry.getValue(), preferencesKey + "=" + newProps.get(entry.getKey())));
|
||||
preferences.put(preferencesKey, newProps.get(entry.getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
PreferencesMap addedProps = platformRewriteProps.subTree("added");
|
||||
for (Map.Entry<String, String> entry : addedProps.entrySet()) {
|
||||
String keyToAdd = entry.getKey();
|
||||
String[] keyToAddParts = keyToAdd.split("\\.");
|
||||
String keyToAddFirstLevel = keyToAddParts[0];
|
||||
String keyToAddSecondLevel = keyToAddParts[0] + "." + keyToAddParts[1];
|
||||
if (!preferences.subTree(keyToAddFirstLevel).isEmpty() && !preferences.subTree(keyToAddSecondLevel).isEmpty() && !preferences.containsKey(keyToAdd)) {
|
||||
System.err.println(I18n.format(_("Warning: platform.txt from core '{0}' misses property {1}, automatically set to {2}. Consider upgrading this core."), platformName, keyToAdd, entry.getValue()));
|
||||
preferences.put(keyToAdd, entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getFolder() {
|
||||
return folder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, TargetBoard> getBoards() {
|
||||
return boards;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferencesMap getCustomMenus() {
|
||||
return customMenus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getCustomMenuIds() {
|
||||
return customMenus.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, PreferencesMap> getProgrammers() {
|
||||
return programmers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferencesMap getProgrammer(String programmer) {
|
||||
return getProgrammers().get(programmer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferencesMap getTool(String tool) {
|
||||
return getPreferences().subTree("tools").subTree(tool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferencesMap getPreferences() {
|
||||
return preferences;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetBoard getBoard(String boardId) {
|
||||
if (boards.containsKey(boardId)) {
|
||||
return boards.get(boardId);
|
||||
}
|
||||
return defaultBoard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetPackage getContainerPackage() {
|
||||
return containerPackage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String res = "TargetPlatform: name=" + id + " boards={\n";
|
||||
for (String boardId : boards.keySet())
|
||||
res += " " + boardId + " = " + boards.get(boardId) + "\n";
|
||||
return res + "}";
|
||||
}
|
||||
}
|
@ -1,76 +1,51 @@
|
||||
/*
|
||||
TargetBoard - Represents a hardware board
|
||||
Part of the Arduino project - http://www.arduino.cc/
|
||||
|
||||
Copyright (c) 2014 Cristian Maglie
|
||||
|
||||
This program 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
package processing.app.debug;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
import static processing.app.I18n.format;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
|
||||
public class TargetBoard {
|
||||
|
||||
private String id;
|
||||
private PreferencesMap prefs;
|
||||
private Map<String, PreferencesMap> menuOptions = new LinkedHashMap<String, PreferencesMap>();
|
||||
private TargetPlatform containerPlatform;
|
||||
|
||||
/**
|
||||
* Create a TargetBoard based on preferences passed as argument.
|
||||
*
|
||||
* @param _prefs
|
||||
* @return
|
||||
*/
|
||||
public TargetBoard(String _id, PreferencesMap _prefs, TargetPlatform parent) {
|
||||
containerPlatform = parent;
|
||||
id = _id;
|
||||
prefs = new PreferencesMap(_prefs);
|
||||
|
||||
// Setup sub-menus
|
||||
PreferencesMap menus = prefs.firstLevelMap().get("menu");
|
||||
if (menus != null)
|
||||
menuOptions = menus.firstLevelMap();
|
||||
|
||||
// Auto generate build.board if not set
|
||||
if (!prefs.containsKey("build.board")) {
|
||||
String board = containerPlatform.getId() + "_" + id;
|
||||
board = board.toUpperCase();
|
||||
prefs.put("build.board", board);
|
||||
System.out
|
||||
.println(format(
|
||||
_("Board {0}:{1}:{2} doesn''t define a ''build.board'' preference. Auto-set to: {3}"),
|
||||
containerPlatform.getContainerPackage().getId(),
|
||||
containerPlatform.getId(), id, board));
|
||||
}
|
||||
}
|
||||
public interface TargetBoard {
|
||||
|
||||
/**
|
||||
* Get the name of the board.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getName() {
|
||||
return prefs.get("name");
|
||||
}
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* Get the identifier of the board
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
public String getId();
|
||||
|
||||
/**
|
||||
* Get the full preferences map of the board with a given identifier
|
||||
* Get the full preferences map of the board
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public PreferencesMap getPreferences() {
|
||||
return prefs;
|
||||
}
|
||||
public PreferencesMap getPreferences();
|
||||
|
||||
/**
|
||||
* Check if the board has a sub menu.
|
||||
@ -79,9 +54,7 @@ public class TargetBoard {
|
||||
* The menu ID to check
|
||||
* @return
|
||||
*/
|
||||
public boolean hasMenu(String menuId) {
|
||||
return menuOptions.containsKey(menuId);
|
||||
}
|
||||
public boolean hasMenu(String menuId);
|
||||
|
||||
/**
|
||||
* Returns the options available on a specific menu
|
||||
@ -90,9 +63,7 @@ public class TargetBoard {
|
||||
* The menu ID
|
||||
* @return
|
||||
*/
|
||||
public PreferencesMap getMenuLabels(String menuId) {
|
||||
return menuOptions.get(menuId).topLevelMap();
|
||||
}
|
||||
public PreferencesMap getMenuLabels(String menuId);
|
||||
|
||||
/**
|
||||
* Returns the label of the specified option in the specified menu
|
||||
@ -103,13 +74,9 @@ public class TargetBoard {
|
||||
* The option ID
|
||||
* @return
|
||||
*/
|
||||
public String getMenuLabel(String menuId, String selectionId) {
|
||||
return getMenuLabels(menuId).get(selectionId);
|
||||
}
|
||||
public String getMenuLabel(String menuId, String selectionId);
|
||||
|
||||
public Set<String> getMenuIds() {
|
||||
return menuOptions.keySet();
|
||||
}
|
||||
public Set<String> getMenuIds();
|
||||
|
||||
/**
|
||||
* Returns the configuration parameters to override (as a PreferenceMap) when
|
||||
@ -121,12 +88,8 @@ public class TargetBoard {
|
||||
* The option ID
|
||||
* @return
|
||||
*/
|
||||
public PreferencesMap getMenuPreferences(String menuId, String selectionId) {
|
||||
return menuOptions.get(menuId).subTree(selectionId);
|
||||
}
|
||||
public PreferencesMap getMenuPreferences(String menuId, String selectionId);
|
||||
|
||||
public TargetPlatform getContainerPlatform() {
|
||||
return containerPlatform;
|
||||
}
|
||||
public TargetPlatform getContainerPlatform();
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
/*
|
||||
TargetPackage - Represents a hardware package
|
||||
Part of the Arduino project - http://www.arduino.cc/
|
||||
|
||||
Copyright (c) 2011 Cristian Maglie
|
||||
Copyright (c) 2014 Cristian Maglie
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -21,61 +20,18 @@
|
||||
*/
|
||||
package processing.app.debug;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import processing.app.I18n;
|
||||
import processing.app.helpers.filefilters.OnlyDirs;
|
||||
public interface TargetPackage {
|
||||
|
||||
public class TargetPackage {
|
||||
String getId();
|
||||
|
||||
private String id;
|
||||
Map<String, TargetPlatform> getPlatforms();
|
||||
|
||||
Map<String, TargetPlatform> platforms = new LinkedHashMap<String, TargetPlatform>();
|
||||
Collection<TargetPlatform> platforms();
|
||||
|
||||
public TargetPackage(String _id, File _folder) throws TargetPlatformException {
|
||||
id = _id;
|
||||
TargetPlatform get(String platform);
|
||||
|
||||
File[] folders = _folder.listFiles(new OnlyDirs());
|
||||
if (folders == null)
|
||||
return;
|
||||
|
||||
for (File subFolder : folders) {
|
||||
if (!subFolder.exists() || !subFolder.canRead())
|
||||
continue;
|
||||
String arch = subFolder.getName();
|
||||
try {
|
||||
TargetPlatform platform = new TargetPlatform(arch, subFolder, this);
|
||||
platforms.put(arch, platform);
|
||||
} catch (TargetPlatformException e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (platforms.size() == 0) {
|
||||
throw new TargetPlatformException(I18n
|
||||
.format(_("No valid hardware definitions found in folder {0}."),
|
||||
_folder.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, TargetPlatform> getPlatforms() {
|
||||
return platforms;
|
||||
}
|
||||
|
||||
public Collection<TargetPlatform> platforms() {
|
||||
return platforms.values();
|
||||
}
|
||||
|
||||
public TargetPlatform get(String platform) {
|
||||
return platforms.get(platform);
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
boolean hasPlatform(TargetPlatform platform);
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
/*
|
||||
TargetPlatform - Represents a hardware platform
|
||||
Part of the Arduino project - http://www.arduino.cc/
|
||||
|
||||
Copyright (c) 2009 David A. Mellis
|
||||
Copyright (c) 2014 Arduino
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -21,174 +20,78 @@
|
||||
*/
|
||||
package processing.app.debug;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
import static processing.app.I18n.format;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
|
||||
public class TargetPlatform {
|
||||
public interface TargetPlatform {
|
||||
|
||||
private String id;
|
||||
private File folder;
|
||||
private TargetPackage containerPackage;
|
||||
public String getId();
|
||||
|
||||
public File getFolder();
|
||||
|
||||
/**
|
||||
* Contains preferences for every defined board
|
||||
* Get TargetBoards under this TargetPlatform into a Map that maps the board
|
||||
* id with the corresponding TargetBoard
|
||||
*
|
||||
* @return a Map<String, TargetBoard>
|
||||
*/
|
||||
private Map<String, TargetBoard> boards = new LinkedHashMap<String, TargetBoard>();
|
||||
private TargetBoard defaultBoard;
|
||||
public Map<String, TargetBoard> getBoards();
|
||||
|
||||
public PreferencesMap getCustomMenus();
|
||||
|
||||
/**
|
||||
* Contains preferences for every defined programmer
|
||||
* Return ids for top level menus
|
||||
*
|
||||
* @return a Set<String> with the ids of the top level custom menus
|
||||
*/
|
||||
private Map<String, PreferencesMap> programmers = new LinkedHashMap<String, PreferencesMap>();
|
||||
public Set<String> getCustomMenuIds();
|
||||
|
||||
/**
|
||||
* Contains preferences for platform
|
||||
* Get preferences for all programmers
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private PreferencesMap preferences = new PreferencesMap();
|
||||
public Map<String, PreferencesMap> getProgrammers();
|
||||
|
||||
/**
|
||||
* Contains labels for top level menus
|
||||
* Get preferences for a specific programmer
|
||||
*
|
||||
* @param programmer
|
||||
* @return
|
||||
*/
|
||||
private PreferencesMap customMenus = new PreferencesMap();
|
||||
public PreferencesMap getProgrammer(String programmer);
|
||||
|
||||
public TargetPlatform(String _name, File _folder, TargetPackage parent)
|
||||
throws TargetPlatformException {
|
||||
/**
|
||||
* Get preferences for a specific tool
|
||||
*
|
||||
* @param tool
|
||||
* @return
|
||||
*/
|
||||
public PreferencesMap getTool(String tool);
|
||||
|
||||
id = _name;
|
||||
folder = _folder;
|
||||
containerPackage = parent;
|
||||
/**
|
||||
* Return TargetPlatform preferences
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public PreferencesMap getPreferences();
|
||||
|
||||
// If there is no boards.txt, this is not a valid 1.5 hardware folder
|
||||
File boardsFile = new File(folder, "boards.txt");
|
||||
if (!boardsFile.exists() || !boardsFile.canRead())
|
||||
throw new TargetPlatformException(
|
||||
format(_("Could not find boards.txt in {0}. Is it pre-1.5?"),
|
||||
folder.getAbsolutePath()));
|
||||
/**
|
||||
* Get a target board
|
||||
*
|
||||
* @param boardId
|
||||
* @return
|
||||
*/
|
||||
public TargetBoard getBoard(String boardId);
|
||||
|
||||
// Load boards
|
||||
try {
|
||||
Map<String, PreferencesMap> boardsPreferences = new PreferencesMap(
|
||||
boardsFile).firstLevelMap();
|
||||
/**
|
||||
* Get the TargetPackage that contains this TargetPlatform
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public TargetPackage getContainerPackage();
|
||||
|
||||
// Create custom menus for this platform
|
||||
PreferencesMap menus = boardsPreferences.get("menu");
|
||||
if (menus != null)
|
||||
customMenus = menus.topLevelMap();
|
||||
boardsPreferences.remove("menu");
|
||||
|
||||
// Create boards
|
||||
Set<String> boardIds = boardsPreferences.keySet();
|
||||
for (String boardId : boardIds) {
|
||||
PreferencesMap preferences = boardsPreferences.get(boardId);
|
||||
TargetBoard board = new TargetBoard(boardId, preferences, this);
|
||||
boards.put(boardId, board);
|
||||
|
||||
// Pick the first board as default
|
||||
if (defaultBoard == null)
|
||||
defaultBoard = board;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new TargetPlatformException(format(_("Error loading {0}"),
|
||||
boardsFile.getAbsolutePath()), e);
|
||||
}
|
||||
|
||||
File platformsFile = new File(folder, "platform.txt");
|
||||
try {
|
||||
if (platformsFile.exists() && platformsFile.canRead()) {
|
||||
preferences.load(platformsFile);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new TargetPlatformException(
|
||||
format(_("Error loading {0}"), platformsFile.getAbsolutePath()), e);
|
||||
}
|
||||
|
||||
// Allow overriding values in platform.txt. This allows changing
|
||||
// platform.txt (e.g. to use a system-wide toolchain), without
|
||||
// having to modify platform.txt (which, when running from git,
|
||||
// prevents files being marked as changed).
|
||||
File localPlatformsFile = new File(folder, "platform.local.txt");
|
||||
try {
|
||||
if (localPlatformsFile.exists() && localPlatformsFile.canRead()) {
|
||||
preferences.load(localPlatformsFile);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new TargetPlatformException(
|
||||
format(_("Error loading {0}"), localPlatformsFile.getAbsolutePath()), e);
|
||||
}
|
||||
|
||||
File progFile = new File(folder, "programmers.txt");
|
||||
try {
|
||||
if (progFile.exists() && progFile.canRead()) {
|
||||
PreferencesMap prefs = new PreferencesMap();
|
||||
prefs.load(progFile);
|
||||
programmers = prefs.firstLevelMap();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new TargetPlatformException(format(_("Error loading {0}"), progFile
|
||||
.getAbsolutePath()), e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public File getFolder() {
|
||||
return folder;
|
||||
}
|
||||
|
||||
public Map<String, TargetBoard> getBoards() {
|
||||
return boards;
|
||||
}
|
||||
|
||||
public PreferencesMap getCustomMenus() {
|
||||
return customMenus;
|
||||
}
|
||||
|
||||
public Set<String> getCustomMenuIds() {
|
||||
return customMenus.keySet();
|
||||
}
|
||||
|
||||
public Map<String, PreferencesMap> getProgrammers() {
|
||||
return programmers;
|
||||
}
|
||||
|
||||
public PreferencesMap getProgrammer(String programmer) {
|
||||
return getProgrammers().get(programmer);
|
||||
}
|
||||
|
||||
public PreferencesMap getTool(String tool) {
|
||||
return getPreferences().subTree("tools").subTree(tool);
|
||||
}
|
||||
|
||||
public PreferencesMap getPreferences() {
|
||||
return preferences;
|
||||
}
|
||||
|
||||
public TargetBoard getBoard(String boardId) {
|
||||
if (boards.containsKey(boardId)) {
|
||||
return boards.get(boardId);
|
||||
}
|
||||
return defaultBoard;
|
||||
}
|
||||
|
||||
public TargetPackage getContainerPackage() {
|
||||
return containerPackage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String res = "TargetPlatform: name=" + id + " boards={\n";
|
||||
for (String boardId : boards.keySet())
|
||||
res += " " + boardId + " = " + boards.get(boardId) + "\n";
|
||||
return res + "}";
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,5 @@
|
||||
package processing.app.helpers;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import processing.app.BaseNoGui;
|
||||
import processing.app.I18n;
|
||||
import processing.app.PreferencesData;
|
||||
@ -16,34 +8,59 @@ import processing.app.debug.TargetPackage;
|
||||
import processing.app.debug.TargetPlatform;
|
||||
import processing.app.legacy.PApplet;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
|
||||
public class CommandlineParser {
|
||||
|
||||
protected static enum ACTION { GUI, NOOP, VERIFY, UPLOAD, GET_PREF };
|
||||
private enum ACTION {
|
||||
GUI, NOOP, VERIFY("--verify"), UPLOAD("--upload"), GET_PREF("--get-pref"), INSTALL_BOARD("--install-boards"), INSTALL_LIBRARY("--install-library");
|
||||
|
||||
private final String value;
|
||||
|
||||
ACTION() {
|
||||
this.value = null;
|
||||
}
|
||||
|
||||
ACTION(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
private ACTION action = ACTION.GUI;
|
||||
private boolean doVerboseBuild = false;
|
||||
private boolean doVerboseUpload = false;
|
||||
private boolean doUseProgrammer = false;
|
||||
private boolean preserveTempFiles;
|
||||
private boolean noUploadPort = false;
|
||||
private boolean forceSavePrefs = false;
|
||||
private String getPref = null;
|
||||
private String getPref;
|
||||
private String boardToInstall;
|
||||
private String libraryToInstall;
|
||||
private List<String> filenames = new LinkedList<String>();
|
||||
|
||||
public static CommandlineParser newCommandlineParser(String[] args) {
|
||||
return new CommandlineParser(args);
|
||||
}
|
||||
|
||||
|
||||
private CommandlineParser(String[] args) {
|
||||
parseArguments(args);
|
||||
checkAction();
|
||||
}
|
||||
|
||||
|
||||
private void parseArguments(String[] args) {
|
||||
// Map of possible actions and corresponding options
|
||||
final Map<String, ACTION> actions = new HashMap<String, ACTION>();
|
||||
actions.put("--verify", ACTION.VERIFY);
|
||||
actions.put("--upload", ACTION.UPLOAD);
|
||||
actions.put("--get-pref", ACTION.GET_PREF);
|
||||
actions.put("--install-boards", ACTION.INSTALL_BOARD);
|
||||
actions.put("--install-library", ACTION.INSTALL_LIBRARY);
|
||||
|
||||
// Check if any files were passed in on the command line
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
@ -56,10 +73,25 @@ public class CommandlineParser {
|
||||
}
|
||||
if (a == ACTION.GET_PREF) {
|
||||
i++;
|
||||
if (i >= args.length)
|
||||
BaseNoGui.showError(null, _("Argument required for --get-pref"), 3);
|
||||
if (i >= args.length) {
|
||||
BaseNoGui.showError(null, I18n.format(_("Argument required for {0}"), a.value), 3);
|
||||
}
|
||||
getPref = args[i];
|
||||
}
|
||||
if (a == ACTION.INSTALL_BOARD) {
|
||||
i++;
|
||||
if (i >= args.length) {
|
||||
BaseNoGui.showError(null, I18n.format(_("Argument required for {0}"), a.value), 3);
|
||||
}
|
||||
boardToInstall = args[i];
|
||||
}
|
||||
if (a == ACTION.INSTALL_LIBRARY) {
|
||||
i++;
|
||||
if (i >= args.length) {
|
||||
BaseNoGui.showError(null, I18n.format(_("Argument required for {0}"), a.value), 3);
|
||||
}
|
||||
libraryToInstall = args[i];
|
||||
}
|
||||
action = a;
|
||||
continue;
|
||||
}
|
||||
@ -74,6 +106,12 @@ public class CommandlineParser {
|
||||
action = ACTION.NOOP;
|
||||
continue;
|
||||
}
|
||||
if (args[i].equals("--preserve-temp-files")) {
|
||||
preserveTempFiles = true;
|
||||
if (action == ACTION.GUI)
|
||||
action = ACTION.NOOP;
|
||||
continue;
|
||||
}
|
||||
if (args[i].equals("--verbose-build")) {
|
||||
doVerboseBuild = true;
|
||||
if (action == ACTION.GUI)
|
||||
@ -164,7 +202,7 @@ public class CommandlineParser {
|
||||
filenames.add(args[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void checkAction() {
|
||||
if ((action == ACTION.UPLOAD || action == ACTION.VERIFY) && filenames.size() != 1)
|
||||
BaseNoGui.showError(null, _("Must specify exactly one sketch file"), 3);
|
||||
@ -179,7 +217,7 @@ public class CommandlineParser {
|
||||
private void processBoardArgument(String selectBoard) {
|
||||
// No board selected? Nothing to do
|
||||
if (selectBoard == null)
|
||||
return;
|
||||
return;
|
||||
|
||||
String[] split = selectBoard.split(":", 4);
|
||||
|
||||
@ -251,27 +289,27 @@ public class CommandlineParser {
|
||||
public List<String> getFilenames() {
|
||||
return filenames;
|
||||
}
|
||||
|
||||
|
||||
public boolean isGetPrefMode() {
|
||||
return action == ACTION.GET_PREF;
|
||||
}
|
||||
|
||||
|
||||
public boolean isGuiMode() {
|
||||
return action == ACTION.GUI;
|
||||
}
|
||||
|
||||
|
||||
public boolean isNoOpMode() {
|
||||
return action == ACTION.NOOP;
|
||||
}
|
||||
|
||||
|
||||
public boolean isUploadMode() {
|
||||
return action == ACTION.UPLOAD;
|
||||
}
|
||||
|
||||
|
||||
public boolean isVerifyMode() {
|
||||
return action == ACTION.VERIFY;
|
||||
}
|
||||
|
||||
|
||||
public boolean isVerifyOrUploadMode() {
|
||||
return isVerifyMode() || isUploadMode();
|
||||
}
|
||||
@ -284,4 +322,23 @@ public class CommandlineParser {
|
||||
return noUploadPort;
|
||||
}
|
||||
|
||||
public boolean isInstallBoard() {
|
||||
return action == ACTION.INSTALL_BOARD;
|
||||
}
|
||||
|
||||
public boolean isInstallLibrary() {
|
||||
return action == ACTION.INSTALL_LIBRARY;
|
||||
}
|
||||
|
||||
public String getBoardToInstall() {
|
||||
return this.boardToInstall;
|
||||
}
|
||||
|
||||
public String getLibraryToInstall() {
|
||||
return libraryToInstall;
|
||||
}
|
||||
|
||||
public boolean isPreserveTempFiles() {
|
||||
return preserveTempFiles;
|
||||
}
|
||||
}
|
||||
|
@ -73,17 +73,28 @@ public class FileUtils {
|
||||
}
|
||||
|
||||
public static void recursiveDelete(File file) {
|
||||
if (file == null)
|
||||
if (file == null) {
|
||||
return;
|
||||
}
|
||||
if (file.isDirectory()) {
|
||||
for (File current : file.listFiles())
|
||||
File[] files = file.listFiles();
|
||||
if (files == null) {
|
||||
return;
|
||||
}
|
||||
for (File current : files) {
|
||||
recursiveDelete(current);
|
||||
}
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
|
||||
public static File createTempFolder() throws IOException {
|
||||
File tmpFolder = new File(System.getProperty("java.io.tmpdir"), "arduino_" + new Random().nextInt(1000000));
|
||||
return createTempFolderIn(new File(System.getProperty("java.io.tmpdir")));
|
||||
}
|
||||
|
||||
public static File createTempFolderIn(File parent) throws IOException {
|
||||
File tmpFolder = new File(parent, "arduino_"
|
||||
+ new Random().nextInt(1000000));
|
||||
if (!tmpFolder.mkdir()) {
|
||||
throw new IOException("Unable to create temp folder " + tmpFolder);
|
||||
}
|
||||
@ -249,5 +260,21 @@ public class FileUtils {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static File newFile(File parent, String... parts) {
|
||||
File result = parent;
|
||||
for (String part : parts) {
|
||||
result = new File(result, part);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean deleteIfExists(File file) {
|
||||
if (file == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return file.delete();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ public abstract class NetUtils {
|
||||
|
||||
private static boolean isReachableByEcho(InetAddress address) {
|
||||
try {
|
||||
return address.isReachable(100);
|
||||
return address.isReachable(300);
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
@ -38,7 +38,7 @@ public abstract class NetUtils {
|
||||
Socket socket = null;
|
||||
try {
|
||||
socket = new Socket();
|
||||
socket.connect(new InetSocketAddress(address, port), 300);
|
||||
socket.connect(new InetSocketAddress(address, port), 1000);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
|
@ -21,18 +21,14 @@
|
||||
*/
|
||||
package processing.app.helpers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import processing.app.legacy.PApplet;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import processing.app.legacy.PApplet;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class PreferencesMap extends LinkedHashMap<String, String> {
|
||||
|
||||
@ -71,7 +67,15 @@ public class PreferencesMap extends LinkedHashMap<String, String> {
|
||||
* @throws IOException
|
||||
*/
|
||||
public void load(File file) throws IOException {
|
||||
load(new FileInputStream(file));
|
||||
FileInputStream fileInputStream = null;
|
||||
try {
|
||||
fileInputStream = new FileInputStream(file);
|
||||
load(fileInputStream);
|
||||
} finally {
|
||||
if (fileInputStream != null) {
|
||||
fileInputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected String processPlatformSuffix(String key, String suffix, boolean isCurrentPlatform) {
|
||||
@ -311,7 +315,7 @@ public class PreferencesMap extends LinkedHashMap<String, String> {
|
||||
* insensitive compared), <b>false</b> in any other case
|
||||
*/
|
||||
public boolean getBoolean(String key) {
|
||||
return new Boolean(get(key));
|
||||
return Boolean.valueOf(get(key));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,4 +26,18 @@ public class StringUtils {
|
||||
String regex = pattern.replace("?", ".?").replace("*", ".*?");
|
||||
return input.matches(regex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string without trailing whitespace characters
|
||||
*
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
public static String rtrim(String s) {
|
||||
int i = s.length() - 1;
|
||||
while (i >= 0 && Character.isWhitespace(s.charAt(i))) {
|
||||
i--;
|
||||
}
|
||||
return s.substring(0, i + 1);
|
||||
}
|
||||
}
|
||||
|
@ -32,11 +32,17 @@ import java.io.FilenameFilter;
|
||||
*/
|
||||
public class OnlyDirs implements FilenameFilter {
|
||||
|
||||
public boolean accept(File dir, String name) {
|
||||
if (name.charAt(0) == '.')
|
||||
return false;
|
||||
if (name.equals("CVS"))
|
||||
return false;
|
||||
return new File(dir, name).isDirectory();
|
||||
}
|
||||
public boolean accept(File dir, String name) {
|
||||
if (name.charAt(0) == '.')
|
||||
return false;
|
||||
if (name.equals("CVS"))
|
||||
return false;
|
||||
return new File(dir, name).isDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
* An handy pre-instantiated object
|
||||
*/
|
||||
public static final OnlyDirs ONLY_DIRS = new OnlyDirs();
|
||||
|
||||
}
|
||||
|
@ -29,13 +29,15 @@ public class OnlyFilesWithExtension implements FilenameFilter {
|
||||
String extensions[];
|
||||
|
||||
public OnlyFilesWithExtension(String... ext) {
|
||||
extensions = ext;
|
||||
this.extensions = ext;
|
||||
}
|
||||
|
||||
public boolean accept(File dir, String name) {
|
||||
for (String ext : extensions)
|
||||
if (name.endsWith(ext))
|
||||
for (String ext : extensions) {
|
||||
if (name.endsWith(ext)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,6 @@
|
||||
package processing.app.legacy;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.*;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.StringTokenizer;
|
||||
@ -276,15 +266,26 @@ public class PApplet {
|
||||
}
|
||||
|
||||
static public String[] loadStrings(File file) {
|
||||
InputStream is = createInput(file);
|
||||
if (is != null) return loadStrings(is);
|
||||
return null;
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = createInput(file);
|
||||
if (is != null) return loadStrings(is);
|
||||
return null;
|
||||
} finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public String[] loadStrings(InputStream input) {
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
BufferedReader reader =
|
||||
new BufferedReader(new InputStreamReader(input, "UTF-8"));
|
||||
reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
|
||||
|
||||
String lines[] = new String[100];
|
||||
int lineCount = 0;
|
||||
@ -297,7 +298,6 @@ public class PApplet {
|
||||
}
|
||||
lines[lineCount++] = line;
|
||||
}
|
||||
reader.close();
|
||||
|
||||
if (lineCount == lines.length) {
|
||||
return lines;
|
||||
@ -311,6 +311,15 @@ public class PApplet {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
//throw new RuntimeException("Error inside loadStrings()");
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -321,14 +330,29 @@ public class PApplet {
|
||||
|
||||
|
||||
static public void saveStrings(File file, String strings[]) {
|
||||
saveStrings(createOutput(file), strings);
|
||||
OutputStream outputStream = null;
|
||||
try {
|
||||
outputStream = createOutput(file);
|
||||
saveStrings(outputStream, strings);
|
||||
} finally {
|
||||
if (outputStream != null) {
|
||||
try {
|
||||
outputStream.close();
|
||||
} catch (IOException e) {
|
||||
//noop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static public void saveStrings(OutputStream output, String strings[]) {
|
||||
PrintWriter writer = createWriter(output);
|
||||
for (int i = 0; i < strings.length; i++) {
|
||||
writer.println(strings[i]);
|
||||
if (writer == null) {
|
||||
return;
|
||||
}
|
||||
for (String string : strings) {
|
||||
writer.println(string);
|
||||
}
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
151
arduino-core/src/processing/app/linux/GTKLookAndFeelFixer.java
Normal file
151
arduino-core/src/processing/app/linux/GTKLookAndFeelFixer.java
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
|
||||
*/
|
||||
|
||||
package processing.app.linux;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class GTKLookAndFeelFixer {
|
||||
|
||||
/*
|
||||
* All functions of this class courtesy of Klaus Reimer
|
||||
* https://www.ailis.de/~k/archives/67-Workaround-for-borderless-Java-Swing-menus-on-Linux.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is free and unencumbered software released into the public domain.
|
||||
*
|
||||
* Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
* distribute this software, either in source code form or as a compiled
|
||||
* binary, for any purpose, commercial or non-commercial, and by any
|
||||
* means.
|
||||
*
|
||||
* In jurisdictions that recognize copyright laws, the author or authors
|
||||
* of this software dedicate any and all copyright interest in the
|
||||
* software to the public domain. We make this dedication for the benefit
|
||||
* of the public at large and to the detriment of our heirs and
|
||||
* successors. We intend this dedication to be an overt act of
|
||||
* relinquishment in perpetuity of all present and future rights to this
|
||||
* software under copyright law.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* For more information, please refer to <http://unlicense.org/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Swing menus are looking pretty bad on Linux when the GTK LaF is used (See
|
||||
* bug #6925412). It will most likely never be fixed anytime soon so this
|
||||
* method provides a workaround for it. It uses reflection to change the GTK
|
||||
* style objects of Swing so popup menu borders have a minimum thickness of
|
||||
* 1 and menu separators have a minimum vertical thickness of 1.
|
||||
*/
|
||||
public static void installGtkPopupBugWorkaround() {
|
||||
// Get current look-and-feel implementation class
|
||||
LookAndFeel laf = UIManager.getLookAndFeel();
|
||||
Class<?> lafClass = laf.getClass();
|
||||
|
||||
// Do nothing when not using the problematic LaF
|
||||
if (!lafClass.getName().equals("com.sun.java.swing.plaf.gtk.GTKLookAndFeel")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We do reflection from here on. Failure is silently ignored. The
|
||||
// workaround is simply not installed when something goes wrong here
|
||||
try {
|
||||
// Access the GTK style factory
|
||||
Field field = lafClass.getDeclaredField("styleFactory");
|
||||
boolean accessible = field.isAccessible();
|
||||
field.setAccessible(true);
|
||||
Object styleFactory = field.get(laf);
|
||||
field.setAccessible(accessible);
|
||||
|
||||
// Fix the horizontal and vertical thickness of popup menu style
|
||||
Object style = getGtkStyle(styleFactory, new JPopupMenu(), "POPUP_MENU");
|
||||
fixGtkThickness(style, "yThickness");
|
||||
fixGtkThickness(style, "xThickness");
|
||||
|
||||
// Fix the vertical thickness of the popup menu separator style
|
||||
style = getGtkStyle(styleFactory, new JSeparator(), "POPUP_MENU_SEPARATOR");
|
||||
fixGtkThickness(style, "yThickness");
|
||||
} catch (Exception e) {
|
||||
// Silently ignored. Workaround can't be applied.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called internally by installGtkPopupBugWorkaround to fix the thickness
|
||||
* of a GTK style field by setting it to a minimum value of 1.
|
||||
*
|
||||
* @param style The GTK style object.
|
||||
* @param fieldName The field name.
|
||||
* @throws Exception When reflection fails.
|
||||
*/
|
||||
private static void fixGtkThickness(Object style, String fieldName) throws Exception {
|
||||
Field field = style.getClass().getDeclaredField(fieldName);
|
||||
boolean accessible = field.isAccessible();
|
||||
field.setAccessible(true);
|
||||
field.setInt(style, Math.max(1, field.getInt(style)));
|
||||
field.setAccessible(accessible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called internally by installGtkPopupBugWorkaround. Returns a specific
|
||||
* GTK style object.
|
||||
*
|
||||
* @param styleFactory The GTK style factory.
|
||||
* @param component The target component of the style.
|
||||
* @param regionName The name of the target region of the style.
|
||||
* @return The GTK style.
|
||||
* @throws Exception When reflection fails.
|
||||
*/
|
||||
private static Object getGtkStyle(Object styleFactory, JComponent component, String regionName) throws Exception {
|
||||
// Create the region object
|
||||
Class<?> regionClass = Class.forName("javax.swing.plaf.synth.Region");
|
||||
Field field = regionClass.getField(regionName);
|
||||
Object region = field.get(regionClass);
|
||||
|
||||
// Get and return the style
|
||||
Class<?> styleFactoryClass = styleFactory.getClass();
|
||||
Method method = styleFactoryClass.getMethod("getStyle", JComponent.class, regionClass);
|
||||
boolean accessible = method.isAccessible();
|
||||
method.setAccessible(true);
|
||||
Object style = method.invoke(styleFactory, component, region);
|
||||
method.setAccessible(accessible);
|
||||
return style;
|
||||
}
|
||||
}
|
@ -26,10 +26,12 @@ import org.apache.commons.exec.CommandLine;
|
||||
import org.apache.commons.exec.Executor;
|
||||
import processing.app.PreferencesData;
|
||||
import processing.app.debug.TargetPackage;
|
||||
import processing.app.tools.ExternalProcessExecutor;
|
||||
import processing.app.legacy.PConstants;
|
||||
import processing.app.tools.CollectStdOutExecutor;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@ -42,17 +44,7 @@ public class Platform extends processing.app.Platform {
|
||||
// TODO Need to be smarter here since KDE people ain't gonna like that GTK.
|
||||
// It may even throw a weird exception at 'em for their trouble.
|
||||
public void setLookAndFeel() throws Exception {
|
||||
// Linux is by default even uglier than metal (Motif?).
|
||||
// Actually, i'm using native menus, so they're even uglier
|
||||
// and Motif-looking (Lesstif?). Ick. Need to fix this.
|
||||
//String lfname = UIManager.getCrossPlatformLookAndFeelClassName();
|
||||
//UIManager.setLookAndFeel(lfname);
|
||||
|
||||
// For 0120, trying out the gtk+ look and feel as the default.
|
||||
// This is available in Java 1.4.2 and later, and it can't possibly
|
||||
// be any worse than Metal. (Ocean might also work, but that's for
|
||||
// Java 1.5, and we aren't going there yet)
|
||||
//UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
|
||||
GTKLookAndFeelFixer.installGtkPopupBugWorkaround();
|
||||
}
|
||||
|
||||
|
||||
@ -130,8 +122,9 @@ public class Platform extends processing.app.Platform {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> resolveDeviceAttachedTo(String serial, Map<String, TargetPackage> packages, String devicesListOutput) {
|
||||
assert packages != null;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
Executor executor = new ExternalProcessExecutor(baos);
|
||||
Executor executor = new CollectStdOutExecutor(baos);
|
||||
|
||||
try {
|
||||
CommandLine toDevicePath = CommandLine.parse("udevadm info -q path -n " + serial);
|
||||
|
@ -26,12 +26,12 @@ import cc.arduino.packages.BoardPort;
|
||||
import com.apple.eio.FileManager;
|
||||
import org.apache.commons.exec.CommandLine;
|
||||
import org.apache.commons.exec.Executor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import processing.app.debug.TargetPackage;
|
||||
import processing.app.tools.ExternalProcessExecutor;
|
||||
import processing.app.legacy.PApplet;
|
||||
import processing.app.legacy.PConstants;
|
||||
import processing.app.tools.CollectStdOutExecutor;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Method;
|
||||
@ -45,12 +45,9 @@ import java.util.List;
|
||||
*/
|
||||
public class Platform extends processing.app.Platform {
|
||||
|
||||
private String osArch;
|
||||
|
||||
public void setLookAndFeel() throws Exception {
|
||||
// Use the Quaqua L & F on OS X to make JFileChooser less awful
|
||||
UIManager.setLookAndFeel("ch.randelshofer.quaqua.QuaquaLookAndFeel");
|
||||
// undo quaqua trying to fix the margins, since we've already
|
||||
// hacked that in, bit by bit, over the years
|
||||
UIManager.put("Component.visualMargin", new Insets(1, 1, 1, 1));
|
||||
}
|
||||
|
||||
public Platform() {
|
||||
@ -59,35 +56,18 @@ public class Platform extends processing.app.Platform {
|
||||
Toolkit.getDefaultToolkit();
|
||||
}
|
||||
|
||||
public void init() {
|
||||
public void init() throws IOException {
|
||||
System.setProperty("apple.laf.useScreenMenuBar", "true");
|
||||
/*
|
||||
try {
|
||||
String name = "processing.app.macosx.ThinkDifferent";
|
||||
Class osxAdapter = ClassLoader.getSystemClassLoader().loadClass(name);
|
||||
|
||||
Class[] defArgs = { Base.class };
|
||||
Method registerMethod = osxAdapter.getDeclaredMethod("register", defArgs);
|
||||
if (registerMethod != null) {
|
||||
Object[] args = { this };
|
||||
registerMethod.invoke(osxAdapter, args);
|
||||
}
|
||||
} catch (NoClassDefFoundError e) {
|
||||
// This will be thrown first if the OSXAdapter is loaded on a system without the EAWT
|
||||
// because OSXAdapter extends ApplicationAdapter in its def
|
||||
System.err.println("This version of Mac OS X does not support the Apple EAWT." +
|
||||
"Application Menu handling has been disabled (" + e + ")");
|
||||
discoverRealOsArch();
|
||||
}
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
// This shouldn't be reached; if there's a problem with the OSXAdapter
|
||||
// we should get the above NoClassDefFoundError first.
|
||||
System.err.println("This version of Mac OS X does not support the Apple EAWT. " +
|
||||
"Application Menu handling has been disabled (" + e + ")");
|
||||
} catch (Exception e) {
|
||||
System.err.println("Exception while loading BaseOSX:");
|
||||
e.printStackTrace();
|
||||
}
|
||||
*/
|
||||
private void discoverRealOsArch() throws IOException {
|
||||
CommandLine uname = CommandLine.parse("uname -m");
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
CollectStdOutExecutor executor = new CollectStdOutExecutor(baos);
|
||||
executor.execute(uname);
|
||||
osArch = StringUtils.trim(new String(baos.toByteArray()));
|
||||
}
|
||||
|
||||
|
||||
@ -115,7 +95,7 @@ public class Platform extends processing.app.Platform {
|
||||
|
||||
public void openURL(String url) throws Exception {
|
||||
if (PApplet.javaVersion < 1.6f) {
|
||||
if (url.startsWith("http://")) {
|
||||
if (url.startsWith("http")) {
|
||||
// formerly com.apple.eio.FileManager.openURL(url);
|
||||
// but due to deprecation, instead loading dynamically
|
||||
try {
|
||||
@ -139,7 +119,7 @@ public class Platform extends processing.app.Platform {
|
||||
|
||||
// for Java 1.6, replacing with java.awt.Desktop.browse()
|
||||
// and java.awt.Desktop.open()
|
||||
if (url.startsWith("http://")) { // browse to a location
|
||||
if (url.startsWith("http")) { // browse to a location
|
||||
Method browseMethod =
|
||||
desktopClass.getMethod("browse", new Class[] { URI.class });
|
||||
browseMethod.invoke(desktop, new Object[] { new URI(url) });
|
||||
@ -211,6 +191,7 @@ public class Platform extends processing.app.Platform {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> resolveDeviceAttachedTo(String serial, Map<String, TargetPackage> packages, String devicesListOutput) {
|
||||
assert packages != null;
|
||||
if (devicesListOutput == null) {
|
||||
return super.resolveDeviceAttachedTo(serial, packages, devicesListOutput);
|
||||
}
|
||||
@ -231,7 +212,7 @@ public class Platform extends processing.app.Platform {
|
||||
@Override
|
||||
public String preListAllCandidateDevices() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
Executor executor = new ExternalProcessExecutor(baos);
|
||||
Executor executor = new CollectStdOutExecutor(baos);
|
||||
|
||||
try {
|
||||
CommandLine toDevicePath = CommandLine.parse("/usr/sbin/system_profiler SPUSBDataType");
|
||||
@ -250,11 +231,16 @@ public class Platform extends processing.app.Platform {
|
||||
|
||||
List<BoardPort> filteredPorts = new LinkedList<BoardPort>();
|
||||
for (BoardPort port : ports) {
|
||||
if (!port.getAddress().startsWith("/dev/cu.")) {
|
||||
if (!port.getAddress().startsWith("/dev/tty.")) {
|
||||
filteredPorts.add(port);
|
||||
}
|
||||
}
|
||||
|
||||
return filteredPorts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOsArch() {
|
||||
return osArch;
|
||||
}
|
||||
}
|
||||
|
126
arduino-core/src/processing/app/packages/LegacyUserLibrary.java
Normal file
126
arduino-core/src/processing/app/packages/LegacyUserLibrary.java
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.contributions.libraries.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 "Uncategorized";
|
||||
}
|
||||
|
||||
@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() {
|
||||
return "LegacyLibrary:" + name + "\n";
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +1,42 @@
|
||||
/*
|
||||
* 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.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import processing.app.helpers.FileUtils;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class LibraryList extends ArrayList<Library> {
|
||||
public class LibraryList extends LinkedList<UserLibrary> {
|
||||
|
||||
public LibraryList(LibraryList libs) {
|
||||
super(libs);
|
||||
@ -18,53 +46,46 @@ public class LibraryList extends ArrayList<Library> {
|
||||
super();
|
||||
}
|
||||
|
||||
public Library getByName(String name) {
|
||||
for (Library l : this)
|
||||
public LibraryList(List<UserLibrary> ideLibs) {
|
||||
super(ideLibs);
|
||||
}
|
||||
|
||||
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());
|
||||
if (l != null)
|
||||
remove(l);
|
||||
public void addOrReplace(UserLibrary lib) {
|
||||
remove(lib);
|
||||
add(lib);
|
||||
}
|
||||
|
||||
public void addOrReplaceAll(Collection<? extends Library> c) {
|
||||
for (Library l : c)
|
||||
addOrReplace(l);
|
||||
|
||||
public void remove(UserLibrary lib) {
|
||||
UserLibrary l = getByName(lib.getName());
|
||||
if (l != null)
|
||||
super.remove(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;
|
||||
}
|
||||
|
||||
public boolean hasLibrary(UserLibrary lib) {
|
||||
for (UserLibrary l : this)
|
||||
if (l == lib) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,46 @@
|
||||
/*
|
||||
* 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 cc.arduino.contributions.libraries.ContributedLibrary;
|
||||
import cc.arduino.contributions.libraries.ContributedLibraryReference;
|
||||
import processing.app.helpers.FileUtils;
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import processing.app.helpers.FileUtils;
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
|
||||
public class Library {
|
||||
public class UserLibrary extends ContributedLibrary {
|
||||
|
||||
private String name;
|
||||
private String version;
|
||||
@ -18,44 +48,23 @@ 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<String> architectures;
|
||||
private File folder;
|
||||
private boolean isLegacy;
|
||||
|
||||
private enum LibraryLayout { FLAT, RECURSIVE };
|
||||
private LibraryLayout layout;
|
||||
private List<String> types;
|
||||
private List<String> declaredTypes;
|
||||
|
||||
private static final List<String> MANDATORY_PROPERTIES = Arrays
|
||||
.asList(new String[] { "name", "version", "author", "maintainer",
|
||||
"sentence", "paragraph", "url" });
|
||||
.asList(new String[]{"name", "version", "author", "maintainer",
|
||||
"sentence", "paragraph", "url"});
|
||||
|
||||
private static final List<String> CATEGORIES = Arrays.asList(new String[] {
|
||||
"Display", "Communication", "Signal Input/Output", "Sensors",
|
||||
"Device Control", "Timing", "Data Storage", "Data Processing", "Other",
|
||||
"Uncategorized" });
|
||||
private static final List<String> CATEGORIES = Arrays.asList(new String[]{
|
||||
"Display", "Communication", "Signal Input/Output", "Sensors",
|
||||
"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();
|
||||
@ -66,16 +75,16 @@ public class Library {
|
||||
|
||||
// Compatibility with 1.5 rev.1 libraries:
|
||||
// "email" field changed to "maintainer"
|
||||
if (!properties.containsKey("maintainer") &&
|
||||
properties.containsKey("email"))
|
||||
if (!properties.containsKey("maintainer") && properties.containsKey("email")) {
|
||||
properties.put("maintainer", properties.get("email"));
|
||||
}
|
||||
|
||||
// Compatibility with 1.5 rev.1 libraries:
|
||||
// "arch" folder no longer supported
|
||||
File archFolder = new File(libFolder, "arch");
|
||||
if (archFolder.isDirectory())
|
||||
throw new IOException("'arch' folder is no longer supported! See "
|
||||
+ "http://goo.gl/gfFJzU for more information");
|
||||
+ "http://goo.gl/gfFJzU for more information");
|
||||
|
||||
// Check mandatory properties
|
||||
for (String p : MANDATORY_PROPERTIES)
|
||||
@ -93,7 +102,7 @@ public class Library {
|
||||
File utilFolder = new File(libFolder, "utility");
|
||||
if (utilFolder.exists() && utilFolder.isDirectory()) {
|
||||
throw new IOException(
|
||||
"Library can't use both 'src' and 'utility' folders.");
|
||||
"Library can't use both 'src' and 'utility' folders.");
|
||||
}
|
||||
} else {
|
||||
// Layout with source code on library's root and "utility" folders
|
||||
@ -104,8 +113,7 @@ public class Library {
|
||||
for (File file : libFolder.listFiles()) {
|
||||
if (file.isDirectory()) {
|
||||
if (FileUtils.isSCCSOrHiddenFile(file)) {
|
||||
System.out.println("WARNING: Spurious " + file.getName() +
|
||||
" folder in '" + properties.get("name") + "' library");
|
||||
System.out.println("WARNING: Spurious " + file.getName() + " folder in '" + properties.get("name") + "' library");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -123,110 +131,88 @@ public class Library {
|
||||
if (category == null)
|
||||
category = "Uncategorized";
|
||||
if (!CATEGORIES.contains(category)) {
|
||||
category = "Uncategorized";
|
||||
System.out.println("WARNING: Category '" + category + "' in library " +
|
||||
properties.get("name") + " is not valid. Setting to 'Uncategorized'");
|
||||
properties.get("name") + " is not valid. Setting to 'Uncategorized'");
|
||||
category = "Uncategorized";
|
||||
}
|
||||
|
||||
String license = properties.get("license");
|
||||
if (license == null)
|
||||
if (license == null) {
|
||||
license = "Unspecified";
|
||||
}
|
||||
|
||||
Library res = new Library();
|
||||
res.folder = libFolder;
|
||||
String types = properties.get("types");
|
||||
if (types == null) {
|
||||
types = "Contributed";
|
||||
}
|
||||
List<String> typesList = new LinkedList<String>();
|
||||
for (String type : types.split(",")) {
|
||||
typesList.add(type.trim());
|
||||
}
|
||||
|
||||
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;
|
||||
res.declaredTypes = typesList;
|
||||
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 <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());
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public File getFolder() {
|
||||
return folder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> 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 List<String> getTypes() {
|
||||
return types;
|
||||
}
|
||||
|
||||
public void setTypes(List<String> types) {
|
||||
this.types = types;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLicense() {
|
||||
return license;
|
||||
}
|
||||
@ -235,44 +221,82 @@ public class Library {
|
||||
return CATEGORIES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMaintainer() {
|
||||
return maintainer;
|
||||
}
|
||||
|
||||
@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<ContributedLibraryReference> getRequires() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<String> getDeclaredTypes() {
|
||||
return declaredTypes;
|
||||
}
|
||||
|
||||
protected enum LibraryLayout {
|
||||
FLAT, RECURSIVE
|
||||
}
|
||||
|
||||
protected LibraryLayout layout;
|
||||
|
||||
public File getSrcFolder() {
|
||||
switch (layout) {
|
||||
case FLAT:
|
||||
return getInstalledFolder();
|
||||
case RECURSIVE:
|
||||
return new File(getInstalledFolder(), "src");
|
||||
default:
|
||||
return null; // Keep compiler happy :-(
|
||||
}
|
||||
}
|
||||
|
||||
public boolean useRecursion() {
|
||||
return (layout == LibraryLayout.RECURSIVE);
|
||||
}
|
||||
|
||||
public File getSrcFolder() {
|
||||
switch (layout) {
|
||||
case FLAT:
|
||||
return folder;
|
||||
case RECURSIVE:
|
||||
return new File(folder, "src");
|
||||
default:
|
||||
return null; // Keep compiler happy :-(
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLegacy() {
|
||||
return isLegacy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String res = "Library:";
|
||||
res += " (name=" + name + ")";
|
||||
res += " (version=" + version + ")";
|
||||
res += " (author=" + author + ")";
|
||||
res += " (maintainer=" + maintainer + ")";
|
||||
res += " (sentence=" + sentence + ")";
|
||||
res += " (paragraph=" + paragraph + ")";
|
||||
res += " (url=" + url + ")";
|
||||
res += " (architectures=" + architectures + ")";
|
||||
String res = "Library: " + name + "\n";
|
||||
res += " (version=" + version + ")\n";
|
||||
res += " (author=" + author + ")\n";
|
||||
res += " (maintainer=" + maintainer + ")\n";
|
||||
res += " (sentence=" + sentence + ")\n";
|
||||
res += " (paragraph=" + paragraph + ")\n";
|
||||
res += " (url=" + website + ")\n";
|
||||
res += " (architectures=" + architectures + ")\n";
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
@ -42,6 +42,9 @@ import java.util.regex.*;
|
||||
* Class that orchestrates preprocessing p5 syntax into straight Java.
|
||||
*/
|
||||
public class PdePreprocessor {
|
||||
|
||||
private static final String IMPORT_REGEX = "^\\s*#include\\s*[<\"](\\S+)[\">]";
|
||||
|
||||
// stores number of built user-defined function prototypes
|
||||
public int prototypeCount = 0;
|
||||
|
||||
@ -94,10 +97,9 @@ public class PdePreprocessor {
|
||||
}
|
||||
|
||||
//String importRegexp = "(?:^|\\s|;)(import\\s+)(\\S+)(\\s*;)";
|
||||
String importRegexp = "^\\s*#include\\s*[<\"](\\S+)[\">]";
|
||||
programImports = new ArrayList<String>();
|
||||
|
||||
String[][] pieces = PApplet.matchAll(program, importRegexp);
|
||||
String[][] pieces = PApplet.matchAll(program, IMPORT_REGEX);
|
||||
|
||||
if (pieces != null)
|
||||
for (int i = 0; i < pieces.length; i++)
|
||||
@ -121,6 +123,19 @@ public class PdePreprocessor {
|
||||
return headerCount + prototypeCount;
|
||||
}
|
||||
|
||||
public static List<String> findIncludes(String code){
|
||||
|
||||
String[][] pieces = PApplet.matchAll(code, IMPORT_REGEX);
|
||||
|
||||
ArrayList programImports = new ArrayList<String>();
|
||||
|
||||
if (pieces != null)
|
||||
for (int i = 0; i < pieces.length; i++)
|
||||
programImports.add(pieces[i][1]); // the package name
|
||||
|
||||
return programImports;
|
||||
}
|
||||
|
||||
|
||||
static String substituteUnicode(String program) {
|
||||
// check for non-ascii chars (these will be/must be in unicode format)
|
||||
|
@ -10,9 +10,9 @@ import java.io.OutputStream;
|
||||
/**
|
||||
* Handy process executor, collecting stdout into a given OutputStream
|
||||
*/
|
||||
public class ExternalProcessExecutor extends DefaultExecutor {
|
||||
public class CollectStdOutExecutor extends DefaultExecutor {
|
||||
|
||||
public ExternalProcessExecutor(final OutputStream os) {
|
||||
public CollectStdOutExecutor(final OutputStream stdout) {
|
||||
this.setStreamHandler(new ExecuteStreamHandler() {
|
||||
@Override
|
||||
public void setProcessInputStream(OutputStream outputStream) throws IOException {
|
||||
@ -27,7 +27,7 @@ public class ExternalProcessExecutor extends DefaultExecutor {
|
||||
byte[] buf = new byte[4096];
|
||||
int bytes = -1;
|
||||
while ((bytes = inputStream.read(buf)) != -1) {
|
||||
os.write(buf, 0, bytes);
|
||||
stdout.write(buf, 0, bytes);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
package processing.app.tools;
|
||||
|
||||
import org.apache.commons.exec.DefaultExecutor;
|
||||
import org.apache.commons.exec.ExecuteStreamHandler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Handy process executor, collecting stdout and stderr into given OutputStreams
|
||||
*/
|
||||
public class CollectStdOutStdErrExecutor extends DefaultExecutor {
|
||||
|
||||
public CollectStdOutStdErrExecutor(final OutputStream stdout, final OutputStream stderr) {
|
||||
this.setStreamHandler(new ExecuteStreamHandler() {
|
||||
@Override
|
||||
public void setProcessInputStream(OutputStream outputStream) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProcessErrorStream(InputStream inputStream) throws IOException {
|
||||
byte[] buf = new byte[4096];
|
||||
int bytes = -1;
|
||||
while ((bytes = inputStream.read(buf)) != -1) {
|
||||
stderr.write(buf, 0, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProcessOutputStream(InputStream inputStream) throws IOException {
|
||||
byte[] buf = new byte[4096];
|
||||
int bytes = -1;
|
||||
while ((bytes = inputStream.read(buf)) != -1) {
|
||||
stdout.write(buf, 0, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package processing.app.tools;
|
||||
|
||||
import org.apache.commons.exec.CommandLine;
|
||||
import processing.app.helpers.OSUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class DoubleQuotedArgumentsOnWindowsCommandLine extends CommandLine {
|
||||
|
||||
public DoubleQuotedArgumentsOnWindowsCommandLine(String executable) {
|
||||
super(executable);
|
||||
}
|
||||
|
||||
public DoubleQuotedArgumentsOnWindowsCommandLine(File executable) {
|
||||
super(executable);
|
||||
}
|
||||
|
||||
public DoubleQuotedArgumentsOnWindowsCommandLine(CommandLine other) {
|
||||
super(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandLine addArgument(String argument, boolean handleQuoting) {
|
||||
// Brutal hack to workaround windows command line parsing.
|
||||
// http://stackoverflow.com/questions/5969724/java-runtime-exec-fails-to-escape-characters-properly
|
||||
// http://msdn.microsoft.com/en-us/library/a1y7w461.aspx
|
||||
// http://bugs.sun.com/view_bug.do?bug_id=6468220
|
||||
// http://bugs.sun.com/view_bug.do?bug_id=6518827
|
||||
if (argument.contains("\"") && OSUtils.isWindows()) {
|
||||
argument = argument.replace("\"", "\\\"");
|
||||
}
|
||||
|
||||
return super.addArgument(argument, handleQuoting);
|
||||
}
|
||||
}
|
@ -22,23 +22,21 @@
|
||||
|
||||
package processing.app.windows;
|
||||
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
|
||||
import org.apache.commons.exec.CommandLine;
|
||||
import org.apache.commons.exec.Executor;
|
||||
|
||||
import processing.app.PreferencesData;
|
||||
import processing.app.debug.TargetPackage;
|
||||
import processing.app.legacy.PApplet;
|
||||
import processing.app.legacy.PConstants;
|
||||
import processing.app.tools.ExternalProcessExecutor;
|
||||
import processing.app.tools.CollectStdOutExecutor;
|
||||
import processing.app.windows.Registry.REGISTRY_ROOT_KEY;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@ -55,7 +53,7 @@ public class Platform extends processing.app.Platform {
|
||||
"\\arduino.exe \"%1\"";
|
||||
static final String DOC = "Arduino.Document";
|
||||
|
||||
public void init() {
|
||||
public void init() throws IOException {
|
||||
super.init();
|
||||
|
||||
checkAssociations();
|
||||
@ -244,7 +242,7 @@ public class Platform extends processing.app.Platform {
|
||||
// "Access is denied" in both cygwin and the "dos" prompt.
|
||||
//Runtime.getRuntime().exec("cmd /c " + currentDir + "\\reference\\" +
|
||||
// referenceFile + ".html");
|
||||
if (url.startsWith("http://")) {
|
||||
if (url.startsWith("http")) {
|
||||
// open dos prompt, give it 'start' command, which will
|
||||
// open the url properly. start by itself won't work since
|
||||
// it appears to need cmd
|
||||
@ -281,36 +279,6 @@ public class Platform extends processing.app.Platform {
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
// Code partially thanks to Richard Quirk from:
|
||||
// http://quirkygba.blogspot.com/2009/11/setting-environment-variables-in-java.html
|
||||
|
||||
static WinLibC clib = (WinLibC) Native.loadLibrary("msvcrt", WinLibC.class);
|
||||
|
||||
public interface WinLibC extends Library {
|
||||
//WinLibC INSTANCE = (WinLibC) Native.loadLibrary("msvcrt", WinLibC.class);
|
||||
//libc = Native.loadLibrary("msvcrt", WinLibC.class);
|
||||
public int _putenv(String name);
|
||||
}
|
||||
|
||||
|
||||
public void setenv(String variable, String value) {
|
||||
//WinLibC clib = WinLibC.INSTANCE;
|
||||
clib._putenv(variable + "=" + value);
|
||||
}
|
||||
|
||||
|
||||
public String getenv(String variable) {
|
||||
return System.getenv(variable);
|
||||
}
|
||||
|
||||
|
||||
public int unsetenv(String variable) {
|
||||
//WinLibC clib = WinLibC.INSTANCE;
|
||||
//clib._putenv(variable + "=");
|
||||
//return 0;
|
||||
return clib._putenv(variable + "=");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return PConstants.platformNames[PConstants.WINDOWS];
|
||||
@ -318,6 +286,7 @@ public class Platform extends processing.app.Platform {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> resolveDeviceAttachedTo(String serial, Map<String, TargetPackage> packages, String devicesListOutput) {
|
||||
assert packages != null;
|
||||
if (devicesListOutput == null) {
|
||||
return super.resolveDeviceAttachedTo(serial, packages, devicesListOutput);
|
||||
}
|
||||
@ -338,7 +307,7 @@ public class Platform extends processing.app.Platform {
|
||||
@Override
|
||||
public String preListAllCandidateDevices() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
Executor executor = new ExternalProcessExecutor(baos);
|
||||
Executor executor = new CollectStdOutExecutor(baos);
|
||||
|
||||
try {
|
||||
String listComPorts = new File(System.getProperty("user.dir"), "hardware/tools/listComPorts.exe").getCanonicalPath();
|
||||
@ -350,4 +319,24 @@ public class Platform extends processing.app.Platform {
|
||||
return super.preListAllCandidateDevices();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixPrefsFilePermissions(File prefsFile) throws IOException {
|
||||
//noop
|
||||
}
|
||||
|
||||
public List<File> postInstallScripts(File folder) {
|
||||
List<File> scripts = new LinkedList<File>();
|
||||
scripts.add(new File(folder, "post_install.bat"));
|
||||
return scripts;
|
||||
}
|
||||
|
||||
public void symlink(File something, File somewhere) throws IOException, InterruptedException {
|
||||
}
|
||||
|
||||
public void link(File something, File somewhere) throws IOException, InterruptedException {
|
||||
}
|
||||
|
||||
public void chmod(File file, int mode) throws IOException, InterruptedException {
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user