├── .gitattributes ├── .gitignore ├── .travis.yml ├── HEADER.txt ├── LICENSE.txt ├── README.md ├── build.gradle ├── bump.sh ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── pom.xml └── src └── main └── java └── com └── flowpowered └── plugins ├── Context.java ├── ContextCreator.java ├── InvalidPluginException.java ├── Plugin.java ├── PluginClassLoader.java ├── PluginLoader.java ├── PluginLoggerFactory.java ├── PluginManager.java ├── PluginState.java ├── annotated ├── AnnotatedPlugin.java ├── AnnotatedPluginLoader.java ├── Disable.java ├── Enable.java └── Plugin.java └── simple └── SimplePluginLoader.java /.gitattributes: -------------------------------------------------------------------------------- 1 | # Normalize as LF in the repository, OS native locally 2 | * text=auto 3 | *.java text 4 | 5 | # Binary files that should not be modified 6 | *.dat binary 7 | *.db binary 8 | *.gif binary 9 | *.icns binary 10 | *.ico binary 11 | *.jks binary 12 | *.jpg binary 13 | *.key binary 14 | *.png binary 15 | *.ttf binary 16 | *.wav binary 17 | JavaApplicationStub binary 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build # 2 | ######### 3 | MANIFEST.MF 4 | dependency-reduced-pom.xml 5 | 6 | # Compiled # 7 | ############ 8 | bin 9 | build 10 | dist 11 | lib 12 | out 13 | run 14 | target 15 | *.com 16 | *.class 17 | *.dll 18 | *.exe 19 | *.o 20 | *.so 21 | 22 | # Databases # 23 | ############# 24 | *.db 25 | *.sql 26 | *.sqlite 27 | 28 | # Packages # 29 | ############ 30 | *.7z 31 | *.dmg 32 | *.ear 33 | *.gz 34 | *.iso 35 | *.jar 36 | !/gradle/wrapper/gradle-wrapper.jar 37 | *.rar 38 | *.tar 39 | *.war 40 | *.zip 41 | 42 | # Repository # 43 | ############## 44 | .git 45 | 46 | # Logging # 47 | ########### 48 | /logs 49 | *.log 50 | 51 | # Misc # 52 | ######## 53 | *.bak 54 | *.tmp 55 | 56 | # System # 57 | ########## 58 | .DS_Store 59 | ehthumbs.db 60 | Thumbs.db 61 | 62 | # Project # 63 | ########### 64 | .buildpath 65 | .classpath 66 | .cproject 67 | .externalToolBuilders 68 | .gradle 69 | .idea 70 | .project 71 | .settings 72 | nbproject 73 | atlassian-ide-plugin.xml 74 | build.xml 75 | nb-configuration.xml 76 | *.iml 77 | *.ipr 78 | *.iws 79 | *.launch 80 | *.pydevproject 81 | 82 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Use new Travis-CI infrastructure 2 | sudo: false 3 | 4 | # Source language and JDK version to use 5 | language: java 6 | jdk: oraclejdk8 7 | 8 | # Use cached Maven dependencies 9 | cache: 10 | directories: 11 | - $HOME/.m2 12 | 13 | # Pre-install Maven dependencies 14 | install: mvn dependency:go-offline 15 | 16 | # Compile and test source 17 | script: mvn clean -DbuildNumber=$TRAVIS_BUILD_NUMBER -DciSystem=travis -Dcommit=${TRAVIS_COMMIT:0:7} 18 | 19 | # Fetch resources, run deployment goal/task, and generate Javadocs and reports 20 | after_success: 21 | # Get files for use with build, namely the custom Maven settings.xml and scripts 22 | - "git clone https://github.com/flow/travis-ci-resources.git $HOME/build/flow/travis" 23 | # DEVELOP: Check if commit is not a pull request, if repo is official, if branch is not master; then deploy artifacts 24 | - "[[ $TRAVIS_PULL_REQUEST == false ]] && [[ $TRAVIS_REPO_SLUG == flow/plugins ]] && [[ $TRAVIS_BRANCH == develop ]] && mvn javadoc:jar source:jar deploy --settings $HOME/build/flow/travis/settings.xml" 25 | # RELEASE: Check if commit is not a pull request, if repo is official, if branch is master; then run deployment script 26 | - "[[ $TRAVIS_PULL_REQUEST == false ]] && [[ $TRAVIS_REPO_SLUG == flow/plugins ]] && [[ $TRAVIS_BRANCH == master ]] && $HOME/build/flow/travis/deploy.sh && $HOME/build/flow/travis/gh-pages.sh" 27 | # Generate Javadocs and report for Coveralls.io 28 | - "mvn javadoc:javadoc cobertura:cobertura coveralls:report -DserviceJobId=$TRAVIS_JOB_ID" 29 | 30 | # RELEASE: Deploy JARs to GitHub Releases 31 | 32 | deploy: 33 | provider: releases 34 | api-key: $GITHUB_TOKEN 35 | file_glob: true 36 | file: target/flow-plugins-*.jar 37 | skip_cleanup: true 38 | on: 39 | branch: master 40 | 41 | # Notification services 42 | notifications: 43 | # Disable build status email notifications, until the issue with forks is fixed 44 | email: false 45 | webhooks: 46 | # Send build information and status to Notifico 47 | - http://n.tkte.ch/h/2048/4S4rO20aCRMlaI86VpW3V0RC 48 | 49 | # Environmental system variables 50 | env: 51 | global: 52 | # Make the log output cleaner 53 | - TERM=dumb 54 | # Super secure, encrypted variables! Ssssh! 55 | - secure: "DSON8OMdSIreTxaiot6nC4SFh7QnRJq42u8mB8JaZX5Okb2igXOyKjmkzEfiKjDgRxLniG7du+4+Uvq6daLclN7NBgiREEKIbbFFfVAFB8xz+G197maWTBxA1YE+RRdXzv4EpDXwsUMyi1+c+jH8Je1O6tWd2iyt0wq+zae2pYk=" 56 | - secure: "l4eQqSD5U182HYoDFQq+mL3CGvw/SFBcOpNSdNt+83YmALsKf16lGkH/SduEOcfEjSadAK/SR/m05U7vtoMK0MsmpI0boLiKuMVZDsNNEDXW0j1LsIhb+xYo+p2r1XpQnzVycUoKrqzfMfRxyWw/CpyVqU1n14QUndvxeVGcQc0=" 57 | - secure: "JkjM6NmtoHkclZ3S9bGkHCDdOkWgrhKpX/BCCn2MO1pQkqy7tnT+H5SRqtn2WnnI1EjrymLj8v7YsXaqUMAWcJ1YTboBlqUONFyF0M9ZPqKeRrYxacCxRbGCUtLkJJInr50mw0FK3Z791Vu2SlttnNfxnuiXSx3lTwbKrf3Dl98=" 58 | - secure: "YldDYrOgqEPLxaJ80R6cNJ0q7x3vDBusdWYsHdSIUwcahPGXW8vAxvq7XE04gC1Z5iLh9jsFLasj2ipNo7TupCLEnzjUSbABAI6foaXQGpvzlCZeDnZwvDOZDDIQc4jNIz1VYdTVA/reX/5tBuur57I5oO5HaVl+BIkQhB7GY5Y=" 59 | -------------------------------------------------------------------------------- /HEADER.txt: -------------------------------------------------------------------------------- 1 | This file is part of ${project}, licensed under the MIT License (MIT). 2 | 3 | Copyright (c) ${year} ${name} <${url}/> 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flow Plugins [![License](http://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat)][License] [![Flattr this](http://img.shields.io/badge/flattr-donate-lightgrey.svg?style=flat)][Donate] [![Build Status](http://img.shields.io/travis/flow/plugins/develop.svg?style=flat)](https://travis-ci.org/flow/plugins) [![Coverage Status](http://img.shields.io/coveralls/flow/plugins/develop.svg?style=flat)](https://coveralls.io/r/flow/plugins) 2 | 3 | Extensible and modular library for creating Java-based plugins that are loaded separate from the main codebase at runtime. 4 | 5 | ## Getting Started 6 | * [Examples and code snippets](https://github.com/flow/examples/tree/master/plugins) 7 | * [Official documentation](#documentation) 8 | * [IRC support chat](http://kiwiirc.com/client/irc.esper.net/flow) 9 | * [Issues tracker](https://github.com/flow/plugins/issues) 10 | 11 | ## Source Code 12 | The latest and greatest source can be found here on [GitHub](https://github.com/flow/plugins). If you are using Git, use this command to clone the project: 13 | 14 | git clone git://github.com/flow/plugins.git 15 | 16 | Or download the latest [development archive](https://github.com/flow/caustic/archive/develop.zip) or the latest [stable archive](https://github.com/flow/caustic/archive/master.zip). 17 | 18 | ## Dependencies 19 | We love open-source libraries! This project uses are few of them to make things easier. If you aren't using Maven or Gradle, you'll need these! 20 | * [com.flowpowered:flow-commons](https://oss.sonatype.org/#nexus-search;gav~com.flowpowered~flow-commons~~~) 21 | * [com.flowpowered:flow-persistence](https://oss.sonatype.org/#nexus-search;gav~com.flowpowered~flow-persistence~~~) 22 | * [com.flowpowered:reflections](https://oss.sonatype.org/#nexus-search;gav~com.flowpowered~reflections~~~) 23 | 24 | ## Building from Source 25 | This project can be built with the _latest_ [Java Development Kit](http://oracle.com/technetwork/java/javase/downloads) and [Maven](https://maven.apache.org/) or [Gradle](https://www.gradle.org/). Maven and Gradle are used to simplify dependency management, but using either of them is optional. 26 | 27 | For Maven, the command `mvn clean package` will build the project and will put the compiled JAR in `target`, and `mvn clean install` will copy it to your local Maven repository. 28 | 29 | For Gradle, the command `gradlew` will build the project and will put the compiled JAR in `~/build/distributions`, and `gradlew install` will copy it to your local Maven repository. 30 | 31 | ## Contributing 32 | Are you a talented programmer looking to contribute some code? We'd love the help! 33 | 34 | * Open a pull request with your changes, following our [guidelines and coding standards](CONTRIBUTING.md). 35 | * Please follow the above guidelines for your pull request(s) accepted. 36 | * For help setting up the project, keep reading! 37 | 38 | Love the project? Feel free to [donate] to help continue development! Flow projects are open-source and powered by community members, like yourself. Without you, we wouldn't be here today! 39 | 40 | Don't forget to watch and star our repo to keep up-to-date with the latest Flow development! 41 | 42 | ## Usage 43 | If you're using [Maven](https://maven.apache.org/download.html) to manage project dependencies, simply include the following in your `pom.xml` file: 44 | 45 | 46 | com.flowpowered 47 | flow-plugins 48 | 1.0.0 49 | 50 | 51 | If you're using [Gradle](https://www.gradle.org/) to manage project dependencies, simply include the following in your `build.gradle` file: 52 | 53 | repositories { 54 | mavenCentral() 55 | } 56 | dependencies { 57 | compile 'com.flowpowered:flow-plugins:1.0.0' 58 | } 59 | 60 | If you plan on using snapshots and do not already have the snapshot repo in your repository list, you will need to add this as well: 61 | 62 | https://oss.sonatype.org/content/groups/public/ 63 | 64 | If you'd prefer to manually import the latest .jar file, you can get it [here](https://github.com/flow/plugins/releases). 65 | 66 | ## Documentation 67 | Want to get friendly with the project and put it to good use? Check out the latest [Javadocs](https://flowpowered.com/plugins). 68 | 69 | To generate Javadocs with Maven, use the `mvn javadoc:javadoc` command. To view the Javadocs simply go to `target/site/apidocs/` and open `index.html` in a web browser. 70 | 71 | To generate Javadocs with Gradle, use the `gradlew javadoc` command. To view the Javadocs simply go to `build/docs/javadoc/` and open `index.html` in a web browser. 72 | 73 | ## Version Control 74 | We've adopted the [git flow branching model](http://nvie.com/posts/a-successful-git-branching-model/) in our projects. The creators of git flow released a [short intro video](http://vimeo.com/16018419) to explain the model. 75 | 76 | The `master` branch is production-ready and contains the latest tagged releases. Before a release is made, it is stagged in `release/x` branches before being pushed and tagged in the `master` branch. Small patches from `hotfix/x` branches are also pushed to `master`, and will always have a release version. The `develop` branch is pre-production, and is where we push `feature/x` branches for testing. 77 | 78 | ## Legal Stuff 79 | Flow Plugins is licensed under the [MIT License][License]. Basically, you can do whatever you want as long as you include the original copyright. Please see the `LICENSE.txt` file for details. 80 | 81 | ## Credits 82 | * [Spout](https://spout.org/) and contributors - *where we all began, and for much of the re-licensed code.* 83 | * All the people behind [Java](http://www.oracle.com/technetwork/java/index.html), [Maven](https://maven.apache.org/), and [Gradle](https://www.gradle.org/). 84 | 85 | [Donate]: https://flattr.com/submit/auto?user_id=spout&url=https://github.com/flow/plugins&title=Flow+Plugins&language=Java&tags=github&category=software 86 | [License]: https://tldrlegal.com/l/mit 87 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Default tasks 2 | defaultTasks 'clean', 'licenseFormat', 'build', 'install' 3 | 4 | // Apply plugins 5 | apply plugin: 'java' 6 | apply plugin: 'cobertura' // Coveralls dependency 7 | apply plugin: 'com.github.kt3k.coveralls' 8 | apply plugin: 'license' 9 | apply plugin: 'maven' 10 | apply plugin: 'signing' 11 | 12 | // Project information 13 | ext.projectName = 'Flow Plugins' 14 | group = 'com.flowpowered' 15 | archivesBaseName = 'flow-plugins' 16 | version = '1.0.0' 17 | ext.packaging = 'jar' 18 | ext.inceptionYear = '2013' 19 | ext.url = 'https://flowpowered.com/plugins' 20 | ext.description = 'Extensible and modular library for creating Java-based plugins that are loaded separate from the main codebase at runtime.' 21 | 22 | // Organization information 23 | ext.organization = 'Flow Powered' 24 | ext.organizationUrl = 'https://flowpowered.com' 25 | 26 | // Build properties 27 | ext.buildNumber = project.hasProperty('buildNumber') ? buildNumber : '0' 28 | ext.ciSystem = project.hasProperty('ciSystem') ? ciSystem : 'unknown' 29 | ext.commit = project.hasProperty('commit') ? commit : 'unknown' 30 | 31 | // Build plugin repositories and dependencies 32 | buildscript { 33 | repositories { 34 | mavenLocal() 35 | mavenCentral() 36 | maven { 37 | name = 'sonatype-nexus' 38 | url = 'https://oss.sonatype.org/content/groups/public/' 39 | } 40 | } 41 | dependencies { 42 | classpath 'net.saliman:gradle-cobertura-plugin:2.2.8' // Coveralls dependency 43 | classpath 'nl.javadude.gradle.plugins:license-gradle-plugin:0.10.0' 44 | classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.4.0' 45 | } 46 | } 47 | 48 | // Project repositories 49 | repositories { 50 | mavenLocal() 51 | mavenCentral() 52 | maven { 53 | name = 'sonatype-nexus' 54 | url = 'https://oss.sonatype.org/content/groups/public/' 55 | } 56 | } 57 | 58 | // Project dependencies 59 | dependencies { 60 | compile 'com.flowpowered:flow-commons:1.0.0' 61 | compile 'com.flowpowered:flow-cerealization:0.1.0-SNAPSHOT' 62 | compile 'com.flowpowered:reflections:0.9.9-SNAPSHOT' 63 | } 64 | 65 | // Filter, process, and include resources 66 | processResources { 67 | // Include in final JAR 68 | from(rootProject.rootDir) { 69 | include 'LICENSE.txt' 70 | } 71 | } 72 | 73 | // License header formatting 74 | license { 75 | ext.project = projectName 76 | ext.year = inceptionYear 77 | ext.name = organization 78 | ext.url = organizationUrl 79 | header rootProject.file('HEADER.txt') 80 | ignoreFailures true 81 | strictCheck true 82 | useDefaultMappings false 83 | mapping { java = 'SLASHSTAR_STYLE' } 84 | } 85 | 86 | // Source compiler configuration 87 | configure([compileJava, compileTestJava]) { 88 | sourceCompatibility = '1.7' 89 | targetCompatibility = '1.7' 90 | options.encoding = 'UTF-8' 91 | options.compilerArgs << '-Xlint:all' 92 | options.compilerArgs << '-Xlint:-path' 93 | options.deprecation = true 94 | } 95 | 96 | // JAR manifest configuration 97 | jar.manifest.mainAttributes( 98 | 'Built-By': System.properties['user.name'], 99 | 'Created-By': System.properties['java.vm.version'] + ' (' + System.properties['java.vm.vendor'] + ')', 100 | 'Specification-Title': projectName, 101 | 'Specification-Version': version + '+' + ciSystem + '-b' + buildNumber + '.git-' + commit, 102 | 'Specification-Vendor': organization + ' - ' + organizationUrl) 103 | 104 | // Javadoc doclint configuration 105 | if (JavaVersion.current().isJava8Compatible()) { 106 | allprojects { 107 | tasks.withType(Javadoc) { 108 | options.addStringOption('Xdoclint:none', '-quiet') 109 | } 110 | } 111 | } 112 | 113 | // Coveralls report configuration 114 | cobertura.coverageFormats = ['html', 'xml'] // Coveralls requires xml format 115 | 116 | // Artifact deployment 117 | uploadArchives { 118 | repositories.mavenDeployer { 119 | // Javadoc JAR generation 120 | task javadocJar(type: Jar, dependsOn: javadoc) { 121 | classifier = 'javadoc' 122 | from 'build/docs/javadoc' 123 | } 124 | 125 | // Source JAR generation 126 | task sourcesJar(type: Jar) { 127 | classifier = 'sources' 128 | from sourceSets.main.java.srcDirs 129 | } 130 | 131 | // Set all artifacts 132 | artifacts { 133 | archives jar, javadocJar, sourcesJar 134 | } 135 | 136 | // Tasks and variables based on if release or snapshot 137 | if (version.endsWith('-SNAPSHOT')) { 138 | // Set variable to snapshots repository URL 139 | ext.sonatypeUrl = 'https://oss.sonatype.org/content/repositories/snapshots/' 140 | } else { 141 | // Set variable to releases repository URL 142 | ext.sonatypeUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/' 143 | 144 | // Artifact signing 145 | signing { 146 | // Sign JAR artifacts 147 | sign configurations.archives 148 | 149 | // Sign Maven POM 150 | beforeDeployment { 151 | org.gradle.api.artifacts.maven.MavenDeployment deployment -> signing.signPom(deployment) 152 | } 153 | } 154 | } 155 | 156 | // Set login credentials for repository 157 | repository(url: sonatypeUrl) { 158 | authentication(userName: System.getenv("sonatypeUsername"), password: System.getenv("sonatypePassword")) 159 | } 160 | 161 | // Maven POM generation 162 | pom.project { 163 | name projectName 164 | artifactId archivesBaseName 165 | packaging packaging 166 | inceptionYear inceptionYear 167 | url url 168 | description project.ext.description 169 | 170 | scm { 171 | connection 'scm:git:git://github.com/flow/plugins.git' 172 | developerConnection 'scm:git:ssh://git@github.com:flow/plugins.git' 173 | url 'https://github.com/flow/plugins' 174 | } 175 | 176 | licenses { 177 | license { 178 | name 'MIT License' 179 | url 'https://tldrlegal.com/l/mit' 180 | distribution 'repo' 181 | } 182 | } 183 | 184 | organization { 185 | name organization 186 | url organizationUrl 187 | } 188 | 189 | developers { 190 | developer { 191 | id 'kitskub' 192 | name 'Jack Huey' 193 | email 'kitskub@gmail.com' 194 | } 195 | developer { 196 | id 'Wolf480pl' 197 | name 'Wolf480pl' 198 | email 'wolf480@interia.pl' 199 | } 200 | developer { 201 | id 'lukespragg' 202 | name 'Luke Spragg' 203 | email 'the@wulf.im' 204 | } 205 | } 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /bump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function die_with() { echo "$*" >&2; exit 1; } 4 | 5 | echo "Getting current version from pom.xml" 6 | CURRENT_VERSION="`sed -n 's|.*\(.*\).*|\1|p' pom.xml | awk '{ print $1; exit }'`" 7 | echo "Current version from pom.xml: $CURRENT_VERSION" 8 | 9 | read -p "New version: " NEW_VERSION || die_with "Prompt for new version failed" 10 | 11 | if ! echo $NEW_VERSION | grep -i -- '-SNAPSHOT' >/dev/null; then echo "WARNING: changing to a release version!"; fi 12 | 13 | if [ -f pom.xml ]; then 14 | echo "Updating the project version in pom.xml to $NEW_VERSION" 15 | awk "/${CURRENT_VERSION//./\\.}/{ if (DONE != 1) {gsub(/${CURRENT_VERSION//./\\.}/, \"$NEW_VERSION\"); DONE=1; }} {print;}" < pom.xml > pom.xml.1 && mv -f pom.xml.1 pom.xml || die_with "Failed to update pom.xml!" 16 | fi 17 | 18 | if [ -f build.gradle ]; then 19 | echo "Updating the project version in build.gradle to $NEW_VERSION" 20 | awk "/${CURRENT_VERSION//./\\.}/{ if (DONE != 1) {gsub(/${CURRENT_VERSION//./\\.}/, \"$NEW_VERSION\"); DONE=1; }} {print;}" < build.gradle > build.gradle.1 && mv -f build.gradle.1 build.gradle || die_with "Failed to update build.gradle!" 21 | fi 22 | 23 | if [ -f README.md ]; then 24 | echo "Updating the project version in README.md to $NEW_VERSION" 25 | awk "/${CURRENT_VERSION//./\\.}/{ if (DONE != 1) {gsub(/${CURRENT_VERSION//./\\.}/, \"$NEW_VERSION\"); }} {print;}" < README.md > README.md.1 && mv -f README.md.1 README.md || die_with "Failed to update README.md!" 26 | fi 27 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | signing.keyId= 2 | signing.password= 3 | signing.secretKeyRingFile= 4 | sonatypeUsername= 5 | sonatypePassword= 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flowpowered/plugins/13f9e646ad16e46af9d398530f33c691bf5d21c4/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=http\://services.gradle.org/distributions/gradle-2.6-all.zip 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 6 | Flow Plugins 7 | com.flowpowered 8 | flow-plugins 9 | 1.0.0 10 | jar 11 | 2013 12 | https://flowpowered.com/plugins 13 | Extensible and modular library for creating Java-based plugins that are loaded separate from the main codebase at runtime. 14 | 15 | 16 | 17 | org.sonatype.oss 18 | oss-parent 19 | 9 20 | 21 | 22 | 23 | 24 | UTF-8 25 | 0 26 | unknown 27 | unknown 28 | -Xdoclint:none 29 | 30 | 31 | 32 | 33 | 34 | MIT License 35 | https://tldrlegal.com/l/mit 36 | repo 37 | 38 | 39 | 40 | 41 | 42 | Flow Powered 43 | https://flowpowered.com 44 | 45 | 46 | 47 | 48 | 49 | kitskub 50 | Jack Huey 51 | kitskub@gmail.com 52 | 53 | 54 | Wolf480pl 55 | Wolf480pl 56 | wolf480@interia.pl 57 | 58 | 59 | lukespragg 60 | Luke Spragg 61 | the@wulf.im 62 | 63 | 64 | 65 | 66 | 67 | scm:git:git://github.com/flow/plugins.git 68 | scm:git:ssh://git@github.com:flow/flow-plugins.git 69 | https://github.com/flow/plugins 70 | 71 | 72 | 73 | 74 | travis 75 | https://travis-ci.org/flow/plugins 76 | 77 | 78 | 79 | 80 | github 81 | https://github.com/flow/plugins/issues 82 | 83 | 84 | 85 | 86 | 87 | 88 | com.flowpowered 89 | flow-commons 90 | 1.0.0 91 | 92 | 93 | com.flowpowered 94 | flow-cerealization 95 | 0.1.0-SNAPSHOT 96 | 97 | 98 | com.flowpowered 99 | reflections 100 | 0.9.9-SNAPSHOT 101 | 102 | 103 | 104 | 105 | 106 | clean install 107 | 108 | 109 | 110 | 111 | 112 | false 113 | . 114 | . 115 | 116 | LICENSE.txt 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | com.mycila.maven-license-plugin 126 | maven-license-plugin 127 | 1.10.b1 128 | 129 | 130 | 131 | 132 | ${project.name} 133 | ${project.inceptionYear} 134 | ${project.organization.name} 135 | ${project.organization.url} 136 | 137 | true 138 | UTF-8 139 | true 140 |
HEADER.txt
141 | 142 | SLASHSTAR_STYLE 143 | 144 | 145 | ${project.name} 146 | license 147 | 148 | 149 | src/main/java/** 150 | src/test/java/** 151 | 152 |
153 | clean 154 | 155 | format 156 | 157 |
158 |
159 |
160 | 161 | 162 | org.apache.maven.plugins 163 | maven-compiler-plugin 164 | 3.3 165 | 166 | 1.7 167 | 1.7 168 | 169 | -Xlint:all 170 | -Xlint:-path 171 | 172 | true 173 | true 174 | 175 | 176 | 177 | 178 | org.apache.maven.plugins 179 | maven-jar-plugin 180 | 2.6 181 | 182 | 183 | 184 | ${project.name} 185 | ${project.version}+${ciSystem}-b${buildNumber}.git-${commit} 186 | ${project.organization.name} - ${project.organization.url} 187 | 188 | 189 | 190 | 191 | 192 | 193 | org.apache.maven.plugins 194 | maven-javadoc-plugin 195 | 2.10.3 196 | 197 | false 198 | false 199 | 200 | 201 | 202 | 203 | org.eluder.coveralls 204 | coveralls-maven-plugin 205 | 3.1.0 206 | 207 | 208 | 209 | org.codehaus.mojo 210 | cobertura-maven-plugin 211 | 2.7 212 | 213 | xml 214 | 256m 215 | 216 | 217 |
218 |
219 |
220 | -------------------------------------------------------------------------------- /src/main/java/com/flowpowered/plugins/Context.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Flow Plugins, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2013 Flow Powered 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.flowpowered.plugins; 25 | 26 | /** 27 | * Holds a link to the {@link Plugin} but also is used to hold broader information about what holds the {@link Plugin} (e.g. an engine). 28 | */ 29 | public class Context { 30 | private final Plugin plugin; 31 | 32 | public Context(Plugin plugin) { 33 | this.plugin = plugin; 34 | } 35 | 36 | @SuppressWarnings("unchecked") 37 | public

> P getPlugin() { 38 | // This is inherently unsafe 39 | // Checks should be done before assigning the plugin to this context to ensure that the Plugin's type parameter at least matches the current class 40 | return (P) plugin; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/flowpowered/plugins/ContextCreator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Flow Plugins, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2013 Flow Powered 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.flowpowered.plugins; 25 | 26 | public interface ContextCreator { 27 | C createContext(Plugin plugin); 28 | 29 | public static class NoContextCreator implements ContextCreator { 30 | public static final NoContextCreator INSTANCE = new NoContextCreator(); 31 | @Override 32 | public Context createContext(Plugin plugin) { 33 | return new Context(plugin); 34 | } 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/flowpowered/plugins/InvalidPluginException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Flow Plugins, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2013 Flow Powered 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.flowpowered.plugins; 25 | 26 | public class InvalidPluginException extends Exception { 27 | private static final long serialVersionUID = 15816838168L; 28 | 29 | public InvalidPluginException() { 30 | } 31 | 32 | public InvalidPluginException(String message) { 33 | super(message); 34 | } 35 | 36 | public InvalidPluginException(String message, Throwable cause) { 37 | super(message, cause); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/flowpowered/plugins/Plugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Flow Plugins, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2013 Flow Powered 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.flowpowered.plugins; 25 | 26 | import org.slf4j.Logger; 27 | 28 | public abstract class Plugin { 29 | private String name; 30 | private PluginManager manager; 31 | private C context; 32 | 33 | public PluginManager getManager() { 34 | return manager; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public C getContext() { 42 | return context; 43 | } 44 | 45 | protected abstract void onEnable() throws Exception; 46 | 47 | protected abstract void onDisable() throws Exception; 48 | 49 | public void enable() throws Exception { 50 | manager.enable(this); 51 | } 52 | 53 | public void disable() throws Exception { 54 | manager.disable(this); 55 | } 56 | 57 | public Logger getLogger() { 58 | return manager.getLogger(this); 59 | } 60 | 61 | public PluginState getState() { 62 | return manager.getState(this); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/flowpowered/plugins/PluginClassLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Flow Plugins, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2013 Flow Powered 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.flowpowered.plugins; 25 | 26 | import java.net.URL; 27 | import java.net.URLClassLoader; 28 | import java.util.Collection; 29 | import java.util.Collections; 30 | import java.util.HashMap; 31 | import java.util.Map; 32 | import java.util.Set; 33 | 34 | public class PluginClassLoader extends URLClassLoader { 35 | private final Map> classes = new HashMap<>(); 36 | 37 | public PluginClassLoader(final ClassLoader parent) { 38 | super(new URL[0], parent); 39 | } 40 | 41 | @Override 42 | public void addURL(URL url) { 43 | super.addURL(url); 44 | } 45 | 46 | @Override 47 | protected Class findClass(String name) throws ClassNotFoundException { 48 | Class result = classes.get(name); 49 | if (result != null) { 50 | return result; 51 | } 52 | return super.findClass(name); 53 | } 54 | 55 | public Class defineClass(byte[] clazz) { 56 | return defineClass(null, clazz, 0, clazz.length); 57 | } 58 | 59 | /** 60 | * Returns a set of cached classes' names 61 | * 62 | * @return set of class names 63 | */ 64 | public Set getClassNames() { 65 | return Collections.unmodifiableSet(classes.keySet()); 66 | } 67 | 68 | /** 69 | * Returns a set of cached classes 70 | * 71 | * @return set of classes 72 | */ 73 | public Collection> getClasses() { 74 | return Collections.unmodifiableCollection(classes.values()); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/flowpowered/plugins/PluginLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Flow Plugins, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2013 Flow Powered 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.flowpowered.plugins; 25 | 26 | import java.lang.reflect.Field; 27 | import java.util.Map; 28 | 29 | public abstract class PluginLoader { 30 | private static final Field nameField = PluginLoader.getFieldSilent(Plugin.class, "name"); 31 | private static final Field managerField = PluginLoader.getFieldSilent(Plugin.class, "manager"); 32 | private static final Field contextField = PluginLoader.getFieldSilent(Plugin.class, "context"); 33 | private final ContextCreator contextCreator; 34 | 35 | public PluginLoader(ContextCreator contextCreator) { 36 | this.contextCreator = contextCreator; 37 | } 38 | 39 | public abstract Plugin load(PluginManager manager, String pluginName) throws InvalidPluginException; 40 | 41 | public abstract Map> loadAll(PluginManager manager); 42 | 43 | protected Plugin init(Plugin plugin, String name, PluginManager manager) { 44 | setField(nameField, plugin, name); 45 | setField(managerField, plugin, manager); 46 | setField(contextField, plugin, createContext(plugin)); 47 | return plugin; 48 | } 49 | 50 | public C createContext(Plugin plugin) { 51 | return contextCreator.createContext(plugin); 52 | } 53 | 54 | public static Field getFieldSilent(Class clazz, String name) { 55 | try { 56 | return clazz.getDeclaredField(name); 57 | } catch (NoSuchFieldException | SecurityException ex) { 58 | throw new IllegalStateException(ex); 59 | } 60 | } 61 | 62 | public static void setField(Field f, Object instance, Object value) { 63 | try { 64 | f.setAccessible(true); 65 | f.set(instance, value); 66 | f.setAccessible(false); 67 | } catch (IllegalAccessException | IllegalArgumentException ex) { 68 | throw new IllegalStateException(ex); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/flowpowered/plugins/PluginLoggerFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Flow Plugins, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2013 Flow Powered 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.flowpowered.plugins; 25 | 26 | import org.slf4j.Logger; 27 | 28 | public interface PluginLoggerFactory { 29 | Logger getLogger(String pluginName); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/flowpowered/plugins/PluginManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Flow Plugins, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2013 Flow Powered 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.flowpowered.plugins; 25 | 26 | import java.util.Collection; 27 | import java.util.Collections; 28 | import java.util.HashMap; 29 | import java.util.LinkedList; 30 | import java.util.List; 31 | import java.util.Map; 32 | import java.util.Map.Entry; 33 | 34 | import org.slf4j.Logger; 35 | import org.slf4j.LoggerFactory; 36 | 37 | public class PluginManager { 38 | private final List> loaders = new LinkedList<>(); // TODO: Make this a set and make PluginLoaders hashset/map compatible? 39 | private final Map> plugins = new HashMap<>(); 40 | private final Map, PluginState> states = new HashMap<>(); 41 | private final Logger logger; 42 | private final PluginLoggerFactory logFactory; 43 | 44 | public PluginManager(Logger logger, PluginLoggerFactory factory) { 45 | this.logger = logger; 46 | this.logFactory = factory; 47 | } 48 | 49 | public PluginManager(Logger logger) { 50 | this(logger, defaultPluginLoggerFactory(logger)); 51 | } 52 | 53 | public void enable(Plugin plugin) throws Exception { 54 | if (plugin.getManager() != this) { 55 | throw new IllegalArgumentException("Not our plugin"); 56 | } 57 | // TODO: thread safety 58 | if (states.get(plugin) != PluginState.DISABLED) { 59 | // TODO: don't fail silently 60 | return; 61 | } 62 | states.put(plugin, PluginState.ENABLING); 63 | try { 64 | plugin.onEnable(); 65 | states.put(plugin, PluginState.ENABLED); 66 | } catch (Exception e) { 67 | states.put(plugin, PluginState.DISABLED); // TODO: sure? Maybe add state FAILED ? 68 | throw e; 69 | } 70 | } 71 | 72 | public void disable(Plugin plugin) throws Exception { 73 | if (plugin.getManager() != this) { 74 | throw new IllegalArgumentException("Not our plugin"); 75 | } 76 | // TODO: thread safety 77 | if (states.get(plugin) != PluginState.ENABLED) { 78 | // TODO: don't fail silently 79 | return; 80 | } 81 | states.put(plugin, PluginState.DISABLING); 82 | try { 83 | plugin.onDisable(); 84 | states.put(plugin, PluginState.DISABLED); 85 | } catch (Exception e) { 86 | states.put(plugin, PluginState.DISABLED); // TODO: Now it's state is what? DISABLED ? It failed to disable... add FAILED state maybe? 87 | throw e; 88 | } 89 | } 90 | 91 | protected void addLoader(PluginLoader loader) { 92 | loaders.add(loader); 93 | /* TODO: Don't load all of them like this: 94 | * - this overrides existing ones with the same name 95 | * - this loads more than needed, should be more lazy 96 | * - this scans for them only once and never checks again 97 | */ 98 | Map> all = loader.loadAll(this); 99 | for (Entry> e : all.entrySet()) { 100 | Plugin plugin = e.getValue(); 101 | plugins.put(e.getKey(), plugin); 102 | states.put(plugin, PluginState.DISABLED); 103 | } 104 | } 105 | 106 | public Logger getLogger(Plugin plugin) { 107 | return logFactory.getLogger(plugin.getName()); 108 | } 109 | 110 | public Plugin getPlugin(String name) { 111 | return plugins.get(name); 112 | } 113 | 114 | public PluginState getState(Plugin plugin) { 115 | return states.get(plugin); 116 | } 117 | 118 | public Collection> getPlugins() { 119 | return Collections.unmodifiableCollection(plugins.values()); 120 | } 121 | 122 | protected static PluginLoggerFactory defaultPluginLoggerFactory(Logger logger) { 123 | final String prefix = logger.getName() + "."; 124 | return new PluginLoggerFactory() { 125 | @Override 126 | public Logger getLogger(String pluginName) { 127 | return LoggerFactory.getLogger(prefix + pluginName); 128 | } 129 | }; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/com/flowpowered/plugins/PluginState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Flow Plugins, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2013 Flow Powered 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.flowpowered.plugins; 25 | 26 | public enum PluginState { 27 | DISABLED, ENABLING, ENABLED, DISABLING 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/flowpowered/plugins/annotated/AnnotatedPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Flow Plugins, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2013 Flow Powered 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.flowpowered.plugins.annotated; 25 | 26 | import java.lang.reflect.InvocationTargetException; 27 | import java.lang.reflect.Method; 28 | 29 | import com.flowpowered.plugins.Context; 30 | import com.flowpowered.plugins.Plugin; 31 | 32 | public class AnnotatedPlugin extends Plugin { 33 | private Object annotated; 34 | private Method enable; 35 | private Method disable; 36 | 37 | @Override 38 | protected void onEnable() throws Exception { 39 | try { 40 | if (enable == null) return; 41 | enable.invoke(annotated, getContext()); 42 | } catch (IllegalAccessException | IllegalArgumentException e) { 43 | throw new IllegalStateException("Got exception from reflection even though the method passed our checks", e); 44 | } catch (InvocationTargetException e) { 45 | throw new Exception("Exception in enable method", e.getCause()); 46 | } 47 | } 48 | 49 | @Override 50 | protected void onDisable() throws Exception { 51 | try { 52 | if (disable == null) return; 53 | disable.invoke(annotated, getContext()); 54 | } catch (IllegalAccessException | IllegalArgumentException e) { 55 | throw new IllegalStateException("Got exception from reflection even though the method passed our checks", e); 56 | } catch (InvocationTargetException e) { 57 | throw new Exception("Exception in enable method", e.getCause()); 58 | } 59 | } 60 | 61 | public Object getAnnotated() { 62 | return annotated; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/flowpowered/plugins/annotated/AnnotatedPluginLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Flow Plugins, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2013 Flow Powered 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.flowpowered.plugins.annotated; 25 | 26 | import java.io.IOException; 27 | import java.io.InputStream; 28 | import java.lang.reflect.Field; 29 | import java.lang.reflect.Method; 30 | import java.lang.reflect.Modifier; 31 | import java.net.URL; 32 | import java.net.URLClassLoader; 33 | import java.nio.file.DirectoryStream; 34 | import java.nio.file.Files; 35 | import java.nio.file.Path; 36 | import java.util.HashMap; 37 | import java.util.Map; 38 | import java.util.Set; 39 | 40 | import org.reflections.Reflections; 41 | import org.reflections.scanners.SubTypesScanner; 42 | import org.reflections.scanners.TypeAnnotationsScanner; 43 | import org.reflections.util.ConfigurationBuilder; 44 | 45 | import com.flowpowered.plugins.Context; 46 | import com.flowpowered.plugins.ContextCreator; 47 | import com.flowpowered.plugins.InvalidPluginException; 48 | import com.flowpowered.plugins.PluginClassLoader; 49 | import com.flowpowered.plugins.PluginLoader; 50 | import com.flowpowered.plugins.PluginManager; 51 | import com.flowpowered.plugins.simple.SimplePluginLoader; 52 | 53 | public class AnnotatedPluginLoader extends PluginLoader { 54 | private final ClassLoader cl; 55 | private final Path path; 56 | private static final Field objectField = PluginLoader.getFieldSilent(AnnotatedPlugin.class, "annotated"); 57 | private static final Field enableField = PluginLoader.getFieldSilent(AnnotatedPlugin.class, "enable"); 58 | private static final Field disableField = PluginLoader.getFieldSilent(AnnotatedPlugin.class, "disable"); 59 | 60 | public AnnotatedPluginLoader(ContextCreator contextCreator, Path folder, ClassLoader cl) { 61 | super(contextCreator); 62 | this.cl = cl; 63 | this.path = folder; 64 | } 65 | 66 | protected Path getPath() { 67 | return path; 68 | } 69 | 70 | @Override 71 | public Map> loadAll(PluginManager manager) { 72 | return loadPath(manager, path); 73 | } 74 | 75 | private Map> loadPath(PluginManager manager, Path path) { 76 | Map> loaded = new HashMap<>(); 77 | try { 78 | if (Files.isDirectory(path)) { 79 | for (Path localPath : Files.newDirectoryStream(path, DirectoryStreamFilter.INSTANCE)) { 80 | loaded.putAll(loadPath(manager, localPath)); 81 | } 82 | } else if (path.toString().endsWith(".jar") || path.toString().endsWith("zip")) { 83 | URL url = path.toUri().toURL(); 84 | URLClassLoader ucl = new URLClassLoader(new URL[] { url }); 85 | for (Class plugin : find(url, ucl)) { 86 | checkAndLoad(loaded, plugin, manager, new PluginClassLoader(ucl)); 87 | } 88 | } else if (path.toString().endsWith(".class")) { 89 | InputStream in = Files.newInputStream(path); 90 | byte[] bytes = new byte[in.available()]; 91 | in.read(bytes); 92 | PluginClassLoader pcl = new PluginClassLoader(cl); 93 | Class check = pcl.defineClass(bytes); 94 | checkAndLoad(loaded, check, manager, pcl); 95 | } 96 | } catch (IOException ex) { 97 | ex.printStackTrace(); 98 | } 99 | return loaded; 100 | } 101 | 102 | private void checkAndLoad(Map> loaded, Class check, PluginManager manager, PluginClassLoader pcl) { 103 | Plugin ann = check.getAnnotation(Plugin.class); 104 | String name = ann.name(); 105 | try { 106 | loaded.put(name, load(manager, ann, check, pcl)); 107 | } catch (InvalidPluginException ex) { 108 | ex.printStackTrace(); 109 | } 110 | } 111 | 112 | public AnnotatedPlugin load(PluginManager manager, Plugin annotation, Class clazz, ClassLoader cl) throws InvalidPluginException { 113 | try { 114 | Object annotated = clazz.newInstance(); 115 | AnnotatedPlugin plugin = new AnnotatedPlugin<>(); 116 | return init(plugin, annotation.name(), manager, annotated); 117 | } catch (IllegalArgumentException | IllegalAccessException ex) { 118 | // Shouldn't happen 119 | throw new IllegalStateException(ex); 120 | } catch (InstantiationException ex) { 121 | throw new InvalidPluginException("Cannot instantiate object", ex); 122 | } 123 | } 124 | 125 | protected boolean validateMethod(Method method, Class contextClass) { 126 | if (Modifier.isAbstract(method.getModifiers())) { 127 | // TODO: log 128 | return false; 129 | } 130 | if (!method.isAccessible()) { 131 | // TODO: log 132 | return false; 133 | } 134 | Class[] params = method.getParameterTypes(); 135 | if (params.length != 1) { 136 | // TODO: log 137 | return false; 138 | } 139 | // We can use the generic Context or a specific one 140 | // However, the parameter can never be a subclass 141 | if (!params[0].isAssignableFrom(contextClass)) { 142 | // TODO: log 143 | return false; 144 | } 145 | return true; 146 | } 147 | 148 | protected AnnotatedPlugin init(AnnotatedPlugin plugin, String name, PluginManager manager, Object annotated) throws IllegalArgumentException, IllegalAccessException { 149 | super.init(plugin, name, manager); 150 | Method enable = null; 151 | Method disable = null; 152 | outer: 153 | for (Class cls = annotated.getClass(); cls != null; cls = cls.getSuperclass()) { 154 | for (Method m : cls.getDeclaredMethods()) { 155 | m.setAccessible(true); 156 | boolean canBeEnable = (enable == null && m.isAnnotationPresent(Enable.class)); 157 | boolean canBeDisable = (disable == null && m.isAnnotationPresent(Disable.class)); 158 | if (!(canBeEnable || canBeDisable)) { 159 | continue; 160 | } 161 | if (!validateMethod(m, plugin.getContext().getClass())) { 162 | continue; 163 | } 164 | if (canBeEnable) { 165 | enable = m; 166 | } 167 | if (canBeDisable) { 168 | disable = m; 169 | } 170 | if (enable != null && disable != null) { 171 | break outer; 172 | } 173 | } 174 | } 175 | SimplePluginLoader.setField(objectField, plugin, annotated); 176 | SimplePluginLoader.setField(enableField, plugin, enable); 177 | SimplePluginLoader.setField(disableField, plugin, disable); 178 | return plugin; 179 | } 180 | 181 | @Override 182 | public com.flowpowered.plugins.Plugin load(PluginManager manager, String pluginName) throws InvalidPluginException { 183 | // TODO: remove this 184 | return loadAll(manager).get(pluginName); 185 | } 186 | 187 | public static Set> find(URL url, ClassLoader cl) { 188 | Reflections ref = new Reflections(new ConfigurationBuilder().addUrls(url).addClassLoader(cl).setScanners(new TypeAnnotationsScanner(), new SubTypesScanner())); 189 | return ref.getTypesAnnotatedWith(Plugin.class); 190 | } 191 | 192 | private static class DirectoryStreamFilter implements DirectoryStream.Filter { 193 | private static DirectoryStreamFilter INSTANCE = new DirectoryStreamFilter(); 194 | @Override 195 | public boolean accept(Path entry) throws IOException { 196 | return Files.isDirectory(entry) || entry.getFileName().toString().endsWith(".jar") || entry.getFileName().toString().endsWith(".zip") || entry.getFileName().toString().endsWith(".class"); 197 | } 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /src/main/java/com/flowpowered/plugins/annotated/Disable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Flow Plugins, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2013 Flow Powered 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.flowpowered.plugins.annotated; 25 | 26 | import java.lang.annotation.ElementType; 27 | import java.lang.annotation.Retention; 28 | import java.lang.annotation.RetentionPolicy; 29 | import java.lang.annotation.Target; 30 | 31 | @Target(ElementType.METHOD) 32 | @Retention(RetentionPolicy.RUNTIME) 33 | public @interface Disable { 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/flowpowered/plugins/annotated/Enable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Flow Plugins, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2013 Flow Powered 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.flowpowered.plugins.annotated; 25 | 26 | import java.lang.annotation.ElementType; 27 | import java.lang.annotation.Retention; 28 | import java.lang.annotation.RetentionPolicy; 29 | import java.lang.annotation.Target; 30 | 31 | @Target(ElementType.METHOD) 32 | @Retention(RetentionPolicy.RUNTIME) 33 | public @interface Enable { 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/flowpowered/plugins/annotated/Plugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Flow Plugins, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2013 Flow Powered 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.flowpowered.plugins.annotated; 25 | 26 | import java.lang.annotation.ElementType; 27 | import java.lang.annotation.Retention; 28 | import java.lang.annotation.RetentionPolicy; 29 | import java.lang.annotation.Target; 30 | 31 | @Target(ElementType.TYPE) 32 | @Retention(RetentionPolicy.RUNTIME) 33 | public @interface Plugin { 34 | String name(); 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/flowpowered/plugins/simple/SimplePluginLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Flow Plugins, licensed under the MIT License (MIT). 3 | * 4 | * Copyright (c) 2013 Flow Powered 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.flowpowered.plugins.simple; 25 | 26 | import java.io.IOException; 27 | import java.net.URL; 28 | import java.util.ArrayList; 29 | import java.util.Collections; 30 | import java.util.Enumeration; 31 | import java.util.HashMap; 32 | import java.util.Map; 33 | 34 | import com.flowpowered.cerealization.config.Configuration; 35 | import com.flowpowered.cerealization.config.ConfigurationException; 36 | import com.flowpowered.cerealization.config.ConfigurationNode; 37 | import com.flowpowered.cerealization.config.yaml.YamlConfiguration; 38 | import com.flowpowered.plugins.Context; 39 | import com.flowpowered.plugins.ContextCreator; 40 | import com.flowpowered.plugins.InvalidPluginException; 41 | import com.flowpowered.plugins.Plugin; 42 | import com.flowpowered.plugins.PluginLoader; 43 | import com.flowpowered.plugins.PluginManager; 44 | 45 | public class SimplePluginLoader extends PluginLoader { 46 | private static final String DESCRIPTOR_NAME = "plugin.yml"; 47 | private static final String NAME_KEY = "name"; 48 | private static final String MAIN_KEY = "main"; 49 | private final ClassLoader cl; 50 | private final String descriptorName, nameKey, mainKey; 51 | 52 | public SimplePluginLoader(ContextCreator contextCreator, ClassLoader cl) { 53 | this(contextCreator, cl, DESCRIPTOR_NAME); 54 | } 55 | 56 | public SimplePluginLoader(ContextCreator contextCreator, ClassLoader cl, String descriptorName) { 57 | this(contextCreator, cl, descriptorName, NAME_KEY, MAIN_KEY); 58 | } 59 | 60 | public SimplePluginLoader(ContextCreator contextCreator, ClassLoader cl, String descriptorName, String nameKey, String mainKey) { 61 | super(contextCreator); 62 | this.cl = cl; 63 | this.descriptorName = descriptorName; 64 | this.nameKey = nameKey; 65 | this.mainKey = mainKey; 66 | } 67 | 68 | protected ClassLoader getClassLoader() { 69 | return cl; 70 | } 71 | 72 | @Override 73 | public Plugin load(PluginManager manager, String pluginName) throws InvalidPluginException { 74 | return load(manager, pluginName, findMains()); 75 | } 76 | 77 | protected Plugin load(PluginManager manager, String pluginName, Map mains) throws InvalidPluginException { 78 | String main = mains.get(pluginName); 79 | if (main == null) { 80 | throw new InvalidPluginException("No main class specified"); 81 | } 82 | try { 83 | Class clazz = Class.forName(main, true, cl); 84 | @SuppressWarnings("unchecked") 85 | Class> pluginClass = (Class>) clazz.asSubclass(Plugin.class); 86 | return init(pluginClass.newInstance(), pluginName, manager); 87 | } catch (ClassNotFoundException | ClassCastException | InstantiationException | IllegalAccessException e) { 88 | // TODO: log 89 | e.printStackTrace(); 90 | } catch (ExceptionInInitializerError e) { 91 | throw new InvalidPluginException("Exception in Plugin initialization", e); 92 | } 93 | return null; 94 | } 95 | 96 | @Override 97 | public Map> loadAll(PluginManager manager) { 98 | Map> loaded = new HashMap<>(); 99 | Map mains = findMains(); 100 | for (String name : mains.keySet()) { 101 | Plugin plugin; 102 | try { 103 | plugin = load(manager, name, mains); 104 | if (plugin != null) { 105 | loaded.put(name, plugin); 106 | } 107 | } catch (Exception ex) { 108 | // TODO: log 109 | ex.printStackTrace(); 110 | } 111 | } 112 | return loaded; 113 | } 114 | 115 | protected Map findMains() { 116 | Map mains = new HashMap<>(); 117 | Enumeration urls; 118 | try { 119 | urls = cl.getResources(descriptorName); 120 | } catch (IOException e) { 121 | // TODO log 122 | e.printStackTrace(); 123 | return mains; 124 | } 125 | ArrayList list = Collections.list(urls); 126 | for (URL url : list) { 127 | try { 128 | Configuration conf = new YamlConfiguration(url.openStream()); 129 | conf.load(); 130 | ConfigurationNode name = conf.getChild(nameKey); 131 | if (name == null || name.getString("").isEmpty()) { 132 | // TODO: log 133 | continue; 134 | } 135 | ConfigurationNode main = conf.getChild(mainKey); 136 | if (main == null || main.getString("").isEmpty()) { 137 | // TODO: log 138 | continue; 139 | } 140 | mains.put(name.getString(), main.getString()); 141 | } catch (IOException e) { 142 | // TODO: log 143 | e.printStackTrace(); 144 | } catch (ConfigurationException ex) { 145 | ex.printStackTrace(); 146 | } 147 | 148 | } 149 | return mains; 150 | } 151 | } 152 | --------------------------------------------------------------------------------