2017-01-30 21:22:36 +01:00
package net.ME1312.SubServers.Host ;
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 ;
2017-04-01 07:37:48 +02:00
import net.ME1312.SubServers.Host.Executable.SubCreator ;
import net.ME1312.SubServers.Host.Executable.SubServer ;
2017-01-30 21:22:36 +01:00
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 ;
2017-04-01 18:50:09 +02:00
import org.json.JSONObject ;
2017-01-30 21:22:36 +01:00
import java.io.File ;
2017-04-01 18:50:09 +02:00
import java.io.FileReader ;
2017-01-30 21:22:36 +01:00
import java.lang.reflect.InvocationTargetException ;
import java.net.InetAddress ;
2017-02-08 01:39:18 +01:00
import java.net.SocketException ;
2017-01-30 21:22:36 +01:00
import java.net.URL ;
import java.net.URLDecoder ;
import java.nio.file.Files ;
import java.util.* ;
2017-04-01 18:50:09 +02:00
import java.util.concurrent.TimeUnit ;
2017-01-30 21:22:36 +01:00
/ * *
* SubServers . Host Main Class
* /
public final class SubServers {
2017-04-01 07:37:48 +02:00
public HashMap < String , SubServer > servers = new HashMap < String , SubServer > ( ) ;
public SubCreator creator ;
2017-01-30 21:22:36 +01:00
public Logger log ;
public final UniversalFile dir = new UniversalFile ( new File ( System . getProperty ( " user.dir " ) ) ) ;
public YAMLConfig config ;
2017-04-01 07:37:48 +02:00
public YAMLSection host = null ;
2017-01-30 21:22:36 +01:00
public YAMLSection lang = null ;
public SubDataClient subdata = null ;
public final Version version = new Version ( " 2.11.2a " ) ;
2017-04-03 19:08:00 +02:00
public final Version bversion = null ;
2017-01-30 21:22:36 +01:00
public final SubAPI api = new SubAPI ( this ) ;
private boolean running ;
2017-02-08 01:39:18 +01:00
/ * *
* SubServers . Host Launch
*
* @param args Args
* @throws Exception
* /
2017-01-30 21:22:36 +01:00
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 ) ;
2017-02-08 01:39:18 +01:00
log . info . println ( " Loading SubServers v " + version . toString ( ) + " Libraries... " ) ;
2017-01-30 21:22:36 +01:00
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 ( ) ) ;
2017-02-08 01:39:18 +01:00
log . info . println ( " Created ~/config.yml " ) ;
2017-01-30 21:22:36 +01:00
} 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 ( ) ) ;
2017-02-08 01:39:18 +01:00
log . info . println ( " Updated ~/config.yml " ) ;
2017-01-30 21:22:36 +01:00
}
2017-04-01 07:37:48 +02:00
if ( ! ( new UniversalFile ( dir , " Templates:Spigot Plugins " ) . exists ( ) ) ) {
new UniversalFile ( dir , " Templates:Spigot Plugins " ) . mkdirs ( ) ;
2017-04-03 19:52:28 +02:00
log . info . println ( " SubServers > Created ~/Templates/Spigot Plugins " ) ;
2017-04-01 07:37:48 +02:00
}
if ( ! ( new UniversalFile ( dir , " Templates:Sponge Config " ) . exists ( ) ) ) {
new UniversalFile ( dir , " Templates:Sponge Config " ) . mkdir ( ) ;
2017-04-03 19:52:28 +02:00
log . info . println ( " SubServers > Created ~/Templates/Sponge Config " ) ;
2017-04-01 07:37:48 +02:00
}
if ( ! ( new UniversalFile ( dir , " Templates:Sponge Mods " ) . exists ( ) ) ) {
new UniversalFile ( dir , " Templates:Sponge Mods " ) . mkdir ( ) ;
2017-04-03 19:52:28 +02:00
log . info . println ( " SubServers > Created ~/Templates/Sponge Mods " ) ;
2017-04-01 07:37:48 +02:00
}
2017-04-01 18:50:09 +02:00
if ( new UniversalFile ( dir , " Recently Deleted " ) . exists ( ) ) {
int f = new UniversalFile ( dir , " Recently Deleted " ) . listFiles ( ) . length ;
for ( File file : new UniversalFile ( dir , " Recently Deleted " ) . listFiles ( ) ) {
try {
if ( file . isDirectory ( ) ) {
if ( new UniversalFile ( dir , " Recently Deleted: " + file . getName ( ) + " :info.json " ) . exists ( ) ) {
JSONObject json = new JSONObject ( Util . readAll ( new FileReader ( new UniversalFile ( dir , " Recently Deleted: " + file . getName ( ) + " :info.json " ) ) ) ) ;
if ( json . keySet ( ) . contains ( " Timestamp " ) ) {
if ( TimeUnit . MILLISECONDS . toDays ( Calendar . getInstance ( ) . getTime ( ) . getTime ( ) - json . getLong ( " Timestamp " ) ) > = 7 ) {
Util . deleteDirectory ( file ) ;
f - - ;
2017-04-03 19:52:28 +02:00
log . info . println ( " SubServers > Removed ~/Recently Deleted/ " + file . getName ( ) ) ;
2017-04-01 18:50:09 +02:00
}
} else {
Util . deleteDirectory ( file ) ;
f - - ;
2017-04-03 19:52:28 +02:00
log . info . println ( " SubServers > Removed ~/Recently Deleted/ " + file . getName ( ) ) ;
2017-04-01 18:50:09 +02:00
}
} else {
Util . deleteDirectory ( file ) ;
f - - ;
2017-04-03 19:52:28 +02:00
log . info . println ( " SubServers > Removed ~/Recently Deleted/ " + file . getName ( ) ) ;
2017-04-01 18:50:09 +02:00
}
} else {
Files . delete ( file . toPath ( ) ) ;
f - - ;
2017-04-03 19:52:28 +02:00
log . info . println ( " SubServers > Removed ~/Recently Deleted/ " + file . getName ( ) ) ;
2017-04-01 18:50:09 +02:00
}
} catch ( Exception e ) {
2017-04-03 19:52:28 +02:00
log . error . println ( e ) ;
2017-04-01 18:50:09 +02:00
}
}
if ( f < = 0 ) {
Files . delete ( new UniversalFile ( dir , " Recently Deleted " ) . toPath ( ) ) ;
}
}
2017-01-30 21:22:36 +01:00
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 ] ) ) ;
2017-04-01 07:37:48 +02:00
creator = new SubCreator ( this ) ;
2017-01-30 21:22:36 +01:00
if ( System . getProperty ( " subservers.host.plugins " , " " ) . length ( ) > 0 ) {
long begin = Calendar . getInstance ( ) . getTime ( ) . getTime ( ) ;
long i = 0 ;
2017-02-08 01:39:18 +01:00
log . info . println ( " 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 ( ) ) ,
2017-02-08 01:39:18 +01:00
Arrays . asList ( clazz . getAnnotation ( SubPlugin . class ) . dependencies ( ) ) , Arrays . asList ( clazz . getAnnotation ( SubPlugin . class ) . softDependencies ( ) ) ) ;
if ( plugins . keySet ( ) . contains ( plugin . getName ( ) . toLowerCase ( ) ) ) log . warn . println ( " Duplicate plugin: " + plugin . getName ( ) . toLowerCase ( ) ) ;
2017-02-05 23:03:17 +01:00
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 ) {
2017-02-08 01:39:18 +01:00
log . error . println ( new IllegalPluginException ( e , " Cannot load plugin descriptor for main class: " + main ) ) ;
2017-01-31 01:33:30 +01:00
}
2017-01-30 21:22:36 +01:00
} catch ( ClassCastException e ) {
2017-02-08 01:39:18 +01:00
log . error . println ( new IllegalPluginException ( e , " Main class isn't annotated as a SubPlugin: " + main ) ) ;
2017-01-30 21:22:36 +01:00
} catch ( InvocationTargetException e ) {
2017-02-08 01:39:18 +01:00
log . error . println ( new IllegalPluginException ( e . getTargetException ( ) , " Uncaught exception occurred while loading main class: " + main ) ) ;
2017-01-31 01:33:30 +01:00
} catch ( Throwable e ) {
2017-02-08 01:39:18 +01:00
log . error . println ( 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 ( ) ) ;
2017-02-08 01:39:18 +01:00
log . info . println ( " Loaded " + plugin . getName ( ) + " v " + plugin . getVersion ( ) . toString ( ) + " by " + plugin . getAuthors ( ) . toString ( ) . substring ( 1 , plugin . getAuthors ( ) . toString ( ) . length ( ) - 1 ) ) ;
2017-02-05 23:03:17 +01:00
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-02-08 01:39:18 +01:00
log . error . println ( 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-08 01:39:18 +01:00
log . error . println ( 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 ) ) ;
2017-02-08 01:39:18 +01:00
log . info . println ( 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 ( ) ;
2017-02-08 01:39:18 +01:00
} catch ( SocketException e ) {
log . severe . println ( e ) ;
2017-01-30 21:22:36 +01:00
} catch ( Exception e ) {
2017-02-08 01:39:18 +01:00
log . error . println ( e ) ;
2017-01-30 21:22:36 +01:00
}
}
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 ) {
2017-02-08 01:39:18 +01:00
log . error . println ( new InvocationTargetException ( e , " Uncaught exception while running command " ) ) ;
2017-01-30 21:22:36 +01:00
}
} ) . start ( ) ;
} else {
2017-02-08 01:39:18 +01:00
log . message . println ( " Unknown Command - " + umsg ) ;
2017-01-30 21:22:36 +01:00
}
}
}
}
2017-02-05 23:03:17 +01:00
private void loadDefaults ( ) {
2017-04-01 22:31:57 +02:00
SubCommand . load ( this ) ;
2017-02-05 23:03:17 +01:00
}
2017-02-08 01:39:18 +01:00
/ * *
* Stop SubServers . Host
*
* @param exit Exit Code
* /
2017-01-30 21:22:36 +01:00
public void stop ( int exit ) {
2017-02-08 01:39:18 +01:00
log . info . println ( " Shutting down... " ) ;
2017-01-30 21:22:36 +01:00
running = false ;
2017-02-05 23:03:17 +01:00
SubDisableEvent event = new SubDisableEvent ( this , exit ) ;
api . executeEvent ( event ) ;
2017-04-01 07:37:48 +02:00
List < String > subservers = new ArrayList < String > ( ) ;
subservers . addAll ( servers . keySet ( ) ) ;
for ( String server : subservers ) {
servers . get ( server ) . stop ( ) ;
try {
servers . get ( server ) . waitFor ( ) ;
} catch ( Exception e ) {
log . error . println ( e ) ;
}
}
subservers . clear ( ) ;
servers . clear ( ) ;
if ( creator . isBusy ( ) ) {
creator . terminate ( ) ;
try {
creator . waitFor ( ) ;
} catch ( Exception e ) {
log . error . println ( e ) ;
}
}
try {
Thread . sleep ( 500 ) ;
} catch ( Exception e ) {
log . error . println ( e ) ;
}
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
}
}