2017-01-30 21:22:36 +01:00
package net.ME1312.SubServers.Host ;
2017-02-05 23:03:17 +01:00
import net.ME1312.SubServers.Host.API.Command ;
2017-01-30 21:22:36 +01:00
import net.ME1312.SubServers.Host.API.Event.CommandPreProcessEvent ;
2017-01-31 01:33:30 +01:00
import net.ME1312.SubServers.Host.API.Event.SubDisableEvent ;
2017-01-30 21:22:36 +01:00
import net.ME1312.SubServers.Host.API.Event.SubEnableEvent ;
import net.ME1312.SubServers.Host.API.SubPluginInfo ;
import net.ME1312.SubServers.Host.API.SubPlugin ;
import net.ME1312.SubServers.Host.Library.Config.YAMLConfig ;
import net.ME1312.SubServers.Host.Library.Config.YAMLSection ;
import net.ME1312.SubServers.Host.Library.Exception.IllegalPluginException ;
import net.ME1312.SubServers.Host.Library.Log.FileLogger ;
import net.ME1312.SubServers.Host.Library.Log.Logger ;
import net.ME1312.SubServers.Host.Library.UniversalFile ;
import net.ME1312.SubServers.Host.Library.Util ;
import net.ME1312.SubServers.Host.Library.Version.Version ;
import net.ME1312.SubServers.Host.Network.SubDataClient ;
import java.io.File ;
import java.lang.reflect.InvocationTargetException ;
import java.net.InetAddress ;
import java.net.URL ;
import java.net.URLDecoder ;
import java.nio.file.Files ;
import java.util.* ;
/ * *
* SubServers . Host Main Class
* /
public final class SubServers {
public Logger log ;
public final UniversalFile dir = new UniversalFile ( new File ( System . getProperty ( " user.dir " ) ) ) ;
public YAMLConfig config ;
public YAMLSection lang = null ;
public SubDataClient subdata = null ;
public final Version version = new Version ( " 2.11.2a " ) ;
2017-01-31 01:33:30 +01:00
public final Version bversion = new Version ( 2 ) ;
2017-01-30 21:22:36 +01:00
public final SubAPI api = new SubAPI ( this ) ;
private boolean running ;
public static void main ( String [ ] args ) throws Exception {
new SubServers ( args ) ;
}
private SubServers ( String [ ] args ) {
log = new Logger ( " SubServers " ) ;
try {
Logger . setup ( System . out , System . err , dir ) ;
log . info ( " Loading SubServers v " + version . toString ( ) + " Libraries... " ) ;
dir . mkdirs ( ) ;
new File ( dir , " Plugins " ) . mkdir ( ) ;
if ( ! ( new UniversalFile ( dir , " config.yml " ) . exists ( ) ) ) {
Util . copyFromJar ( SubServers . class . getClassLoader ( ) , " net/ME1312/SubServers/Host/Library/Files/config.yml " , new UniversalFile ( dir , " config.yml " ) . getPath ( ) ) ;
log . info ( " Created ~/config.yml " ) ;
} else if ( ( new Version ( ( new YAMLConfig ( new UniversalFile ( dir , " config.yml " ) ) ) . get ( ) . getSection ( " Settings " ) . getString ( " Version " , " 0 " ) ) . compareTo ( new Version ( " 2.11.2a+ " ) ) ) ! = 0 ) {
Files . move ( new UniversalFile ( dir , " config.yml " ) . toPath ( ) , new UniversalFile ( dir , " config.old " + Math . round ( Math . random ( ) * 100000 ) + " .yml " ) . toPath ( ) ) ;
Util . copyFromJar ( SubServers . class . getClassLoader ( ) , " net/ME1312/SubServers/Host/Library/Files/config.yml " , new UniversalFile ( dir , " config.yml " ) . getPath ( ) ) ;
log . info ( " Updated ~/config.yml " ) ;
}
config = new YAMLConfig ( new UniversalFile ( dir , " config.yml " ) ) ;
subdata = new SubDataClient ( this , config . get ( ) . getSection ( " Settings " ) . getSection ( " SubData " ) . getString ( " Name " , " undefined " ) ,
InetAddress . getByName ( config . get ( ) . getSection ( " Settings " ) . getSection ( " SubData " ) . getString ( " Address " , " 127.0.0.1:4391 " ) . split ( " : " ) [ 0 ] ) ,
Integer . parseInt ( config . get ( ) . getSection ( " Settings " ) . getSection ( " SubData " ) . getString ( " Address " , " 127.0.0.1:4391 " ) . split ( " : " ) [ 1 ] ) ) ;
if ( System . getProperty ( " subservers.host.plugins " , " " ) . length ( ) > 0 ) {
long begin = Calendar . getInstance ( ) . getTime ( ) . getTime ( ) ;
long i = 0 ;
log . info ( " Loading SubAPI Plugins... " ) ;
2017-02-05 23:03:17 +01:00
/ *
* Decode Plugin List Variable
* /
2017-01-31 01:33:30 +01:00
String decoded = URLDecoder . decode ( System . getProperty ( " subservers.host.plugins " ) , " UTF-8 " ) ;
List < String > classes = new LinkedList < String > ( ) ;
HashMap < String , SubPluginInfo > plugins = new LinkedHashMap < String , SubPluginInfo > ( ) ;
if ( ! decoded . contains ( " " ) ) {
classes . add ( decoded ) ;
2017-01-30 21:22:36 +01:00
} else {
2017-01-31 01:33:30 +01:00
classes . addAll ( Arrays . asList ( decoded . split ( " " ) ) ) ;
2017-01-30 21:22:36 +01:00
}
2017-02-05 23:03:17 +01:00
/ *
* Load Main Classes & Plugin Descriptions
* /
2017-01-30 21:22:36 +01:00
for ( String main : classes ) {
try {
Class < ? > clazz = Class . forName ( main ) ;
if ( ! clazz . isAnnotationPresent ( SubPlugin . class ) ) throw new ClassCastException ( " Cannot find plugin descriptor " ) ;
2017-01-31 01:33:30 +01:00
Object obj = clazz . getConstructor ( ) . newInstance ( ) ;
try {
2017-02-05 23:03:17 +01:00
SubPluginInfo plugin = new SubPluginInfo ( this , obj , clazz . getAnnotation ( SubPlugin . class ) . name ( ) , new Version ( clazz . getAnnotation ( SubPlugin . class ) . version ( ) ) ,
2017-01-31 01:33:30 +01:00
Arrays . asList ( clazz . getAnnotation ( SubPlugin . class ) . authors ( ) ) , ( clazz . getAnnotation ( SubPlugin . class ) . description ( ) . length ( ) > 0 ) ? clazz . getAnnotation ( SubPlugin . class ) . description ( ) : null ,
2017-02-05 23:03:17 +01:00
( clazz . getAnnotation ( SubPlugin . class ) . website ( ) . length ( ) > 0 ) ? new URL ( clazz . getAnnotation ( SubPlugin . class ) . website ( ) ) : null , Arrays . asList ( clazz . getAnnotation ( SubPlugin . class ) . loadBefore ( ) ) ,
Arrays . asList ( clazz . getAnnotation ( SubPlugin . class ) . depend ( ) ) , Arrays . asList ( clazz . getAnnotation ( SubPlugin . class ) . softDepend ( ) ) ) ;
if ( plugins . keySet ( ) . contains ( plugin . getName ( ) . toLowerCase ( ) ) ) log . warn ( " Duplicate plugin: " + plugin . getName ( ) . toLowerCase ( ) ) ;
plugin . addExtra ( " subservers.plugin.loadafter " , new ArrayList < String > ( ) ) ;
2017-01-31 01:33:30 +01:00
plugins . put ( plugin . getName ( ) . toLowerCase ( ) , plugin ) ;
} catch ( Throwable e ) {
log . error ( new IllegalPluginException ( e , " Cannot load plugin descriptor for main class: " + main ) ) ;
}
2017-01-30 21:22:36 +01:00
} catch ( ClassCastException e ) {
log . error ( new IllegalPluginException ( e , " Main class isn't annotated as a SubPlugin: " + main ) ) ;
} catch ( InvocationTargetException e ) {
2017-01-31 01:33:30 +01:00
log . error ( new IllegalPluginException ( e . getTargetException ( ) , " Uncaught exception occurred while loading main class: " + main ) ) ;
} catch ( Throwable e ) {
log . error ( new IllegalPluginException ( e , " Cannot load main class: " + main ) ) ;
2017-01-30 21:22:36 +01:00
}
}
2017-02-05 23:03:17 +01:00
/ *
* Load Extra Plugin Settings
* /
for ( SubPluginInfo plugin : plugins . values ( ) ) {
for ( String loadbefore : plugin . getLoadBefore ( ) ) {
if ( plugins . keySet ( ) . contains ( loadbefore . toLowerCase ( ) ) ) {
List < String > loadafter = plugins . get ( loadbefore . toLowerCase ( ) ) . getExtra ( " subservers.plugin.loadafter " ) . asRawStringList ( ) ;
loadafter . add ( plugin . getName ( ) . toLowerCase ( ) ) ;
plugins . get ( loadbefore . toLowerCase ( ) ) . addExtra ( " subservers.plugin.loadafter " , loadafter ) ;
}
}
}
/ *
* Register Plugins
* /
2017-01-30 21:22:36 +01:00
while ( plugins . size ( ) > 0 ) {
List < String > loaded = new ArrayList < String > ( ) ;
2017-02-05 23:03:17 +01:00
for ( SubPluginInfo plugin : plugins . values ( ) ) {
2017-01-30 21:22:36 +01:00
try {
boolean load = true ;
for ( String depend : plugin . getDependancies ( ) ) {
if ( plugins . keySet ( ) . contains ( depend . toLowerCase ( ) ) ) {
load = false ;
} else if ( ! api . plugins . keySet ( ) . contains ( depend . toLowerCase ( ) ) ) {
2017-01-31 01:33:30 +01:00
throw new IllegalPluginException ( new IllegalStateException ( " Unknown dependency: " + depend ) , " Cannot meet requirements for plugin: " + plugin . getName ( ) + " v " + plugin . getVersion ( ) . toString ( ) ) ;
2017-01-30 21:22:36 +01:00
}
}
for ( String softdepend : plugin . getSoftDependancies ( ) ) {
if ( plugins . keySet ( ) . contains ( softdepend . toLowerCase ( ) ) ) {
load = false ;
}
}
2017-02-05 23:03:17 +01:00
for ( String loadafter : plugin . getExtra ( " subservers.plugin.loadafter " ) . asRawStringList ( ) ) {
if ( plugins . keySet ( ) . contains ( loadafter . toLowerCase ( ) ) ) {
load = false ;
2017-01-30 21:22:36 +01:00
}
}
2017-02-05 23:03:17 +01:00
if ( load ) try {
plugin . removeExtra ( " subservers.plugin.loadafter " ) ;
plugin . setEnabled ( true ) ;
api . addListener ( plugin , plugin . get ( ) ) ;
api . plugins . put ( plugin . getName ( ) . toLowerCase ( ) , plugin ) ;
loaded . add ( plugin . getName ( ) . toLowerCase ( ) ) ;
log . info ( " Loaded " + plugin . getName ( ) + " v " + plugin . getVersion ( ) . toString ( ) + " by " + plugin . getAuthors ( ) . toString ( ) . substring ( 1 , plugin . getAuthors ( ) . toString ( ) . length ( ) - 1 ) ) ;
i + + ;
} catch ( Throwable e ) {
plugin . setEnabled ( false ) ;
throw new InvocationTargetException ( e , " Problem loading plugin: " + plugin . getName ( ) ) ;
}
2017-01-31 01:33:30 +01:00
} catch ( InvocationTargetException e ) {
2017-01-30 21:22:36 +01:00
log . error ( e ) ;
2017-02-05 23:03:17 +01:00
loaded . add ( plugin . getName ( ) . toLowerCase ( ) ) ;
2017-01-30 21:22:36 +01:00
}
}
2017-01-31 01:33:30 +01:00
int progress = 0 ;
2017-01-30 21:22:36 +01:00
for ( String name : loaded ) {
2017-01-31 01:33:30 +01:00
progress + + ;
2017-01-30 21:22:36 +01:00
plugins . remove ( name ) ;
}
2017-01-31 01:33:30 +01:00
if ( progress = = 0 & & plugins . size ( ) ! = 0 ) {
2017-02-05 23:03:17 +01:00
log . error ( new IllegalStateException ( " Couldn't load more plugins but there are " + plugins . size ( ) + " more " ) ) ;
2017-01-31 01:33:30 +01:00
break ;
}
2017-01-30 21:22:36 +01:00
}
2017-02-05 23:03:17 +01:00
/ *
* Enable Plugins
* /
api . executeEvent ( new SubEnableEvent ( this ) ) ;
log . info ( i + " Plugin " + ( ( i = = 1 ) ? " " : " s " ) + " loaded in " + ( Calendar . getInstance ( ) . getTime ( ) . getTime ( ) - begin ) + " ms " ) ;
2017-01-30 21:22:36 +01:00
}
2017-02-05 23:03:17 +01:00
loadDefaults ( ) ;
2017-01-30 21:22:36 +01:00
running = true ;
loop ( ) ;
} catch ( Exception e ) {
log . error ( e ) ;
}
}
private void loop ( ) {
Scanner console = new Scanner ( System . in ) ;
while ( running & & console . hasNextLine ( ) ) {
2017-02-05 23:03:17 +01:00
if ( ! running ) continue ;
2017-01-30 21:22:36 +01:00
final String umsg = console . nextLine ( ) ;
final CommandPreProcessEvent event ;
2017-02-05 23:03:17 +01:00
api . executeEvent ( event = new CommandPreProcessEvent ( this , umsg ) ) ;
2017-01-30 21:22:36 +01:00
if ( ! event . isCancelled ( ) ) {
2017-02-05 23:03:17 +01:00
final String cmd = ( umsg . startsWith ( " / " ) ) ? ( ( umsg . contains ( " " ) ? umsg . split ( " " ) : new String [ ] { umsg } ) [ 0 ] . substring ( 1 ) ) : ( ( umsg . contains ( " " ) ? umsg . split ( " " ) : new String [ ] { umsg } ) [ 0 ] ) ;
2017-01-30 21:22:36 +01:00
if ( api . commands . keySet ( ) . contains ( cmd . toLowerCase ( ) ) ) {
ArrayList < String > args = new ArrayList < String > ( ) ;
args . addAll ( Arrays . asList ( umsg . contains ( " " ) ? umsg . split ( " " ) : new String [ ] { umsg } ) ) ;
args . remove ( 0 ) ;
new Thread ( ( ) - > {
try {
api . commands . get ( cmd . toLowerCase ( ) ) . command ( cmd , args . toArray ( new String [ args . size ( ) ] ) ) ;
} catch ( Exception e ) {
log . error ( new InvocationTargetException ( e , " Uncaught exception while running command " ) ) ;
}
} ) . start ( ) ;
} else {
log . info ( " Unknown Command - " + umsg ) ;
}
}
}
}
2017-02-05 23:03:17 +01:00
private void loadDefaults ( ) {
new Command ( null ) {
@Override
public void command ( String handle , String [ ] args ) {
if ( args . length = = 0 ) {
log . info (
System . getProperty ( " os.name " ) + ' ' + System . getProperty ( " os.version " ) + ',' ,
" Java " + System . getProperty ( " java.version " ) + ',' ,
" SubServers.Host v " + version . toString ( ) + ( ( bversion = = null ) ? " " : " BETA " + bversion . toString ( ) ) ) ;
} else if ( api . plugins . get ( args [ 0 ] . toLowerCase ( ) ) ! = null ) {
SubPluginInfo plugin = api . plugins . get ( args [ 0 ] . toLowerCase ( ) ) ;
log . info ( plugin . getName ( ) + " v " + plugin . getVersion ( ) + " by " + plugin . getAuthors ( ) . toString ( ) . substring ( 1 , plugin . getAuthors ( ) . toString ( ) . length ( ) - 1 ) ) ;
if ( plugin . getWebsite ( ) ! = null ) log . info ( plugin . getWebsite ( ) . toString ( ) ) ;
if ( plugin . getDescription ( ) ! = null ) log . info ( " " , plugin . getDescription ( ) ) ;
} else {
log . info ( " There is no plugin with that name " ) ;
}
}
} . usage ( " [plugin] " ) . description ( " Gets the version of the System and SubServers or the specified Plugin " ) . help (
" This command will print what OS you're running, your OS version, " ,
" your Java version, and the SubServers.Host version. " ,
" " ,
" If the [plugin] option is provided, it will print information about the specified plugin instead. " ,
" " ,
" Examples: " ,
" /version " ,
" /version ExamplePlugin "
) . register ( " ver " , " version " ) ;
new Command ( null ) {
public void command ( String handle , String [ ] args ) {
HashMap < String , String > commands = new LinkedHashMap < String , String > ( ) ;
HashMap < Command , String > handles = new LinkedHashMap < Command , String > ( ) ;
int length = 0 ;
for ( String command : api . commands . keySet ( ) ) {
String formatted = " / " ;
Command cmd = api . commands . get ( command ) ;
String alias = ( handles . keySet ( ) . contains ( cmd ) ) ? handles . get ( cmd ) : null ;
if ( alias ! = null ) formatted = commands . get ( alias ) ;
if ( cmd . usage ( ) . length = = 0 | | alias ! = null ) {
formatted = formatted . replaceFirst ( " \\ s " , ( ( alias ! = null ) ? " | " : " " ) + command + ' ' ) ;
} else {
String usage = " " ;
for ( String str : cmd . usage ( ) ) usage + = ( ( usage . length ( ) = = 0 ) ? " " : " " ) + str ;
formatted = formatted . replaceFirst ( " \\ s " , command + ' ' + usage + ' ' ) ;
}
if ( formatted . length ( ) > length ) {
length = formatted . length ( ) ;
}
if ( alias = = null ) {
commands . put ( command , formatted ) ;
handles . put ( cmd , command ) ;
} else {
commands . put ( alias , formatted ) ;
}
}
if ( args . length = = 0 ) {
log . info ( " SubServers.Host Command List: " ) ;
for ( String command : commands . keySet ( ) ) {
String formatted = commands . get ( command ) ;
Command cmd = api . commands . get ( command ) ;
while ( formatted . length ( ) < length ) {
formatted + = ' ' ;
}
formatted + = ( ( cmd . description ( ) = = null | | cmd . description ( ) . length ( ) = = 0 ) ? " " : " - " + cmd . description ( ) ) ;
log . info ( formatted ) ;
}
} else if ( api . commands . keySet ( ) . contains ( ( args [ 0 ] . startsWith ( " / " ) ) ? args [ 0 ] . toLowerCase ( ) . substring ( 1 ) : args [ 0 ] . toLowerCase ( ) ) ) {
Command cmd = api . commands . get ( ( args [ 0 ] . startsWith ( " / " ) ) ? args [ 0 ] . toLowerCase ( ) . substring ( 1 ) : args [ 0 ] . toLowerCase ( ) ) ;
String formatted = commands . get ( Util . getBackwards ( api . commands , cmd ) . get ( 0 ) ) ;
log . info ( formatted . substring ( 0 , formatted . length ( ) - 1 ) ) ;
for ( String line : cmd . help ( ) ) {
log . info ( " " + line ) ;
}
} else {
log . info ( " There is no command with that name " ) ;
}
}
} . usage ( " [command] " ) . description ( " Prints a list of the commands and/or their descriptions " ) . help (
" This command will print a list of all currently registered commands and aliases, " ,
" along with their usage and a short description. " ,
" " ,
" If the [command] option is provided, it will print that command, it's aliases, " ,
" it's usage, and an extended description like the one you see here instead. " ,
" " ,
" Examples: " ,
" /help " ,
" /help end "
) . register ( " help " , " ? " ) ;
new Command ( null ) {
@Override
public void command ( String handle , String [ ] args ) {
stop ( 0 ) ;
}
} . description ( " Stops this SubServers instance " ) . help (
" This command will shutdown this instance of SubServers.Host, " ,
" SubServers running on this host, and any plugins currently running via SubAPI. " ,
" " ,
" Example: " ,
" /stop "
) . register ( " exit " , " end " ) ;
}
2017-01-30 21:22:36 +01:00
public void stop ( int exit ) {
log . info ( " Shutting down... " ) ;
running = false ;
2017-02-05 23:03:17 +01:00
SubDisableEvent event = new SubDisableEvent ( this , exit ) ;
api . executeEvent ( event ) ;
2017-01-30 21:22:36 +01:00
if ( subdata ! = null ) Util . isException ( ( ) - > subdata . destroy ( false ) ) ;
2017-01-31 01:33:30 +01:00
Util . isException ( FileLogger : : end ) ;
System . exit ( event . getExitCode ( ) ) ;
2017-01-30 21:22:36 +01:00
}
}