Skip to content
This repository was archived by the owner on Aug 18, 2020. It is now read-only.

Commit 142775b

Browse files
authored
Merge pull request #91 from daniel0611/feature/41-plugin-structure-rework
Rework plugin structure to replace pluggable with a xml file
2 parents 0d87f09 + 68e0ec8 commit 142775b

File tree

14 files changed

+651
-271
lines changed

14 files changed

+651
-271
lines changed

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ pluginTargetFolderNames := List("plugins", s"target/scala-$scalaMajorVersion/plu
9191
apiProjectPath := "api"
9292
guiProjectPath := "gui"
9393

94-
create := BuildUtility(streams.value.log).createPluginTask(pluginFolderNames.value)
94+
create := PluginCreateWizard(streams.value.log).createPluginTask(pluginFolderNames.value)
9595
fetch := BuildUtility(streams.value.log).fetchPluginsTask(pluginFolderNames.value, pluginBuildFileName.value,
9696
pluginTargetFolderNames.value, apiProjectPath.value)
9797
copy := BuildUtility(streams.value.log).copyPluginsTask(pluginFolderNames.value, pluginTargetFolderNames.value, scalaMajorVersion)

project/BuildUtility.scala

Lines changed: 6 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -131,86 +131,6 @@ class BuildUtility(logger: ManagedLogger) {
131131
logger info s"Successfully copied $successCounter / ${allJarFiles.length} plugins to target '${pluginTargetFolder.getPath}'!"
132132
}
133133

134-
/**
135-
* Creates a new plugin. Interactive command using the console.
136-
*
137-
* @param pluginFolderNames All folder names, containing plugin source code. Defined in build.sbt.
138-
*/
139-
def createPluginTask(pluginFolderNames: List[String]): Unit = {
140-
withTaskInfo("CREATE PLUGIN") {
141-
142-
// Plugin folders have to be defined in the build.sbt file first
143-
if (pluginFolderNames.isEmpty) {
144-
println("Before creating a new plugin, please define at least one plugin source folder in the build.sbt file.")
145-
logger warn "Aborting task without plugin creation."
146-
147-
} else {
148-
println("Welcome to the \"create plugin\"-wizard. Please specify name, version and plugin source folder.")
149-
150-
// Plugin name
151-
val name = BuildUtility.askForInput(
152-
"Please specify the name of the plugin. Do only use characters allowed for directories and files of your OS.",
153-
"Plugin name",
154-
repeatIfEmpty = true
155-
)
156-
157-
// Plugin version (default: 0.1)
158-
var version = BuildUtility.askForInput(
159-
"Please specify the version of the plugin. Just press enter for version \"0.1\".",
160-
"Plugin version",
161-
repeatIfEmpty = false
162-
)
163-
if (version == "") version = "0.1"
164-
165-
// Plugin folder name (must be defined in build.sbt)
166-
var pluginFolderName = ""
167-
while (!pluginFolderNames.contains(pluginFolderName)) {
168-
pluginFolderName = BuildUtility.askForInput(
169-
s"Please specify the plugin source directory. Available directories: ${pluginFolderNames.mkString("[", ", ", "]")}",
170-
"Plugin source directory",
171-
repeatIfEmpty = true
172-
)
173-
}
174-
175-
createPlugin(name, version, pluginFolderName)
176-
}
177-
}
178-
}
179-
180-
private def withTaskInfo(taskName: String)(task: Unit): Unit = BuildUtility.withTaskInfo(taskName, logger)(task)
181-
182-
private def createPlugin(name: String, version: String, pluginFolderName: String): Unit = {
183-
logger info s"Trying to create plugin $name (version $version) at plugin folder $pluginFolderName."
184-
185-
val pluginFolder = new File(pluginFolderName)
186-
if (!pluginFolder.exists()) {
187-
logger error "Plugin source folder does not exist. Aborting task without plugin creation."
188-
189-
} else {
190-
191-
val plugin = new Plugin(pluginFolderName, name)
192-
193-
if (!plugin.createPluginFolder()) {
194-
logger error "Plugin does already exist. Aborting task without plugin creation."
195-
} else {
196-
logger info s"Created plugin '$name'"
197-
198-
if (plugin.createSrcFolder()) {
199-
logger info "Successfully created source folder."
200-
} else {
201-
logger warn "Unable to create source folder."
202-
}
203-
204-
if (plugin.createSbtFile(version)) {
205-
logger info "Successfully created plugins sbt file."
206-
} else {
207-
logger warn "Unable to create plugins sbt file."
208-
}
209-
210-
}
211-
}
212-
}
213-
214134
def guiTask(guiProjectPath: String, cacheDir: File): Unit = {
215135
withTaskInfo("BUILD GUI") {
216136
val guiDir = new File(guiProjectPath)
@@ -234,13 +154,13 @@ class BuildUtility(logger: ManagedLogger) {
234154
/**
235155
* Download the dependencies of the gui using npm.
236156
*
237-
* @param guiDir the directory of the gui.
157+
* @param guiDir the directory of the gui.
238158
* @param cacheDir a dir, where sbt can store files for caching in the "install" sub-dir.
239159
* @return None, if a error occurs which will be displayed, otherwise the output directory with the built gui.
240160
*/
241161
private def installGuiDeps(guiDir: File, cacheDir: File): Option[File] = {
242162
// Check buildGui for a explanation, it's almost the same.
243-
163+
244164
val install = FileFunction.cached(new File(cacheDir, "install"), FilesInfo.hash)(_ => {
245165

246166
logger info "Installing GUI dependencies."
@@ -266,8 +186,8 @@ class BuildUtility(logger: ManagedLogger) {
266186

267187
/**
268188
* Builds the gui using npm.
269-
*
270-
* @param guiDir the directory of the gui.
189+
*
190+
* @param guiDir the directory of the gui.
271191
* @param cacheDir a dir, where sbt can store files for caching in the "build" sub-dir.
272192
* @return None, if a error occurs which will be displayed, otherwise the output directory with the built gui.
273193
*/
@@ -326,25 +246,14 @@ class BuildUtility(logger: ManagedLogger) {
326246
Set(f)
327247
}
328248
}
249+
250+
private def withTaskInfo(taskName: String)(task: Unit): Unit = BuildUtility.withTaskInfo(taskName, logger)(task)
329251
}
330252

331253
object BuildUtility {
332254

333255
def apply(logger: ManagedLogger): BuildUtility = new BuildUtility(logger)
334256

335-
private def askForInput(information: String, description: String, repeatIfEmpty: Boolean): String = {
336-
println(information)
337-
print(s"$description > ")
338-
339-
var input = scala.io.Source.fromInputStream(System.in).bufferedReader().readLine()
340-
println("")
341-
342-
if (input == "" && repeatIfEmpty)
343-
input = askForInput(information, description, repeatIfEmpty)
344-
345-
input
346-
}
347-
348257
/**
349258
* This method can be used to create better readable sbt console output by declaring start and stop of a custom task.
350259
*

project/Plugin.scala

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import java.io.File
22

3+
import sbt.io.IO
4+
5+
import scala.util.Try
6+
import scala.xml.PrettyPrinter
7+
38
/**
49
* A plugin represents a directory in a plugin source directory. Every plugin has its own build file and source folder.
510
*
@@ -26,22 +31,6 @@ class Plugin(val pluginSourceDirectoryName: String, val name: String) {
2631
}
2732
}
2833

29-
/**
30-
* Creates the plugin src folder inside of a plugin folder
31-
*
32-
* @note Make sure to create the plugin folder first!
33-
* @return true, if the process was successful
34-
*/
35-
def createSrcFolder(): Boolean = {
36-
if (new File(s"$pluginDirectoryPath/src").mkdir() &&
37-
new File(s"$pluginDirectoryPath/src/main").mkdir() &&
38-
new File(s"$pluginDirectoryPath/src/main/scala").mkdir()) {
39-
true
40-
} else {
41-
false
42-
}
43-
}
44-
4534
/**
4635
* Creates a simple sbt file with name and version info into the plugin folder
4736
*
@@ -52,7 +41,53 @@ class Plugin(val pluginSourceDirectoryName: String, val name: String) {
5241
val sbtFile = new SbtFile(name, version)
5342

5443
// The name of the sbt file is the plugin name. This worked in first tests
55-
sbtFile.save(s"$pluginDirectoryPath/$name.sbt")
44+
sbtFile.save(s"$pluginDirectoryPath/$normalizedName.sbt")
45+
}
46+
47+
/**
48+
* Generates the plugin.xml file in the resources of the plugin.
49+
*
50+
* @param metadata the metadata for this plugin
51+
* @param author author of this plugin, used by the framework to identify it
52+
*/
53+
def createPluginXMLFile(metadata: PluginMetadata, author: String, version: String, apiVersion: (Int, Int)): Boolean = {
54+
val xml = <plugin>
55+
<name>
56+
{name}
57+
</name>
58+
<author>
59+
{author}
60+
</author>
61+
<version>
62+
{version}
63+
</version>
64+
<api>
65+
<major>{apiVersion._1}</major>
66+
<minor>{apiVersion._2}</minor>
67+
</api>{metadata.toXML}
68+
</plugin>
69+
70+
val trimmed = scala.xml.Utility.trim(xml)
71+
val prettyXml = new PrettyPrinter(100, 2).format(trimmed)
72+
73+
Try(
74+
IO.write(new File(s"$pluginDirectoryPath/src/main/resources/plugin.xml"), prettyXml)
75+
).isSuccess
76+
}
77+
78+
/**
79+
* Generates the main class file implementing PluginImpl for the plugin developer in their choosen language.
80+
*
81+
* @param language the language in with the source file will be generated
82+
* @return true, if everything was successful
83+
*/
84+
def createSourceFile(language: PluginLanguage.Value): Boolean = {
85+
val content = PluginLanguage.getSourceFileContent(normalizedName, language)
86+
val langName = language.toString.toLowerCase
87+
88+
Try(
89+
IO.write(new File(s"$pluginDirectoryPath/src/main/$langName/${normalizedName}Plugin.$langName"), content.getBytes)
90+
).isSuccess
5691
}
5792

5893
/**
@@ -94,7 +129,9 @@ object Plugin {
94129
*/
95130
def getPlugins(pluginSourceFolderName: String): Seq[Plugin] = {
96131
val pluginSourceFolder = new File(pluginSourceFolderName)
97-
pluginSourceFolder.listFiles.filter(_.isDirectory).filter(d => d.getName != ".git" && d.getName != ".github")
132+
pluginSourceFolder.listFiles
133+
.filter(_.isDirectory)
134+
.filter(d => containsPluginXMLFile(d))
98135
.map(folder => new Plugin(pluginSourceFolderName, folder.getName))
99136

100137
}
@@ -110,8 +147,11 @@ object Plugin {
110147
pluginSourceFolder.exists() && pluginSourceFolder.isDirectory
111148
}
112149

113-
private def toPluginPathName(name: String) = name.replace(" ", "").toLowerCase
150+
private def toPluginPathName(name: String) = name.replaceAll("[ -]", "").toLowerCase
114151

152+
private def containsPluginXMLFile(directory: File): Boolean = {
153+
new File(s"$directory/src/main/resources/plugin.xml").exists()
154+
}
115155
}
116156

117157

0 commit comments

Comments
 (0)