/**
* Copyright 2014
* SMEdit https://github.com/StarMade/SMEdit
* SMTools https://github.com/StarMade/SMTools
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
**/
package jo.sm.logic;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.jar.Manifest;
import java.util.logging.Level;
import java.util.logging.Logger;
import jo.sm.data.SparseMatrix;
import jo.sm.data.StarMade;
import jo.sm.logic.utils.BooleanUtils;
import jo.sm.mods.IBlocksPlugin;
import jo.sm.mods.IStarMadePlugin;
import jo.sm.mods.IStarMadePluginFactory;
import jo.sm.ship.data.Block;
import jo.util.Paths;
public class StarMadeLogic {
public static final String INVERT_X_AXIS = "InvertXAxis";
public static final String INVERT_Y_AXIS = "InvertYAxis";
private static StarMade mStarMade;
private static final Logger log = Logger.getLogger(StarMadeLogic.class.getName());
public static synchronized StarMade getInstance() {
if (mStarMade == null) {
mStarMade = new StarMade();
}
return mStarMade;
}
public static void setBaseDir(String baseDir) {
File bd = new File(baseDir);
if (!bd.exists()) {
throw new IllegalArgumentException("Base directory '" + baseDir + "' does not exist");
}
getInstance().setBaseDir(bd);
File ntive = new File(bd, "native");
File libs = null;
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("windows")) {
libs = new File(ntive, "windows");
} else if (!os.contains("mac")) if (os.contains("linux")) {
libs = new File(ntive, "linux");
} else if (os.contains("solaris")) {
libs = new File(ntive, "solaris");
} else {
libs = new File(ntive, "macosx");
}
if (libs != null) {
String path = System.getProperty("java.library.path");
path += File.pathSeparator + libs.toString();
System.setProperty("java.library.path", path);
// trick from http://blog.cedarsoft.com/2010/11/setting-java-library-path-programmatically/
try {
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
log.log(Level.WARNING, "baseDir failed!", e);
e.printStackTrace();
}
}
List<String> blocksPlugins = new ArrayList<>();
List<String> pluginFactories = new ArrayList<>();
discoverPlugins(baseDir, blocksPlugins, pluginFactories);
loadPlugins(blocksPlugins, pluginFactories);
}
private static void loadPlugins(List<String> blocksPlugins, List<String> pluginFactories) {
for (String blocksPluginClassName : blocksPlugins) {
addBlocksPlugin(blocksPluginClassName);
}
for (String pluginFactoryClassName : pluginFactories) {
addPluginFactory(pluginFactoryClassName);
}
}
public static boolean addBlocksPlugin(String blocksPluginClassName) {
try {
Class<?> blocksPluginClass = getInstance().getModLoader().loadClass(blocksPluginClassName);
if (blocksPluginClass == null) {
log.log(Level.WARNING, "No such class: " + blocksPluginClassName);
return false;
}
IBlocksPlugin plugin = (IBlocksPlugin) blocksPluginClass.newInstance();
if (plugin == null) {
log.log(Level.WARNING, "Can't instantiate class: " + blocksPluginClassName);
return false;
}
addBlocksPlugin(plugin);
return true;
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
log.log(Level.WARNING, "plugin failed!", e);
e.printStackTrace();
return false;
}
}
public static boolean addPluginFactory(String pluginFactoryClassName) {
try {
Class<?> pluginFactoryClass = getInstance().getModLoader().loadClass(pluginFactoryClassName);
if (pluginFactoryClass == null) {
return false;
}
IStarMadePluginFactory factory = (IStarMadePluginFactory) pluginFactoryClass.newInstance();
if (factory == null) {
return false;
}
getInstance().getPluginFactories().add(factory);
return true;
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
log.log(Level.WARNING, "pluginFactory failed!", e);
e.printStackTrace();
return false;
}
}
public static void addBlocksPlugin(IBlocksPlugin plugin) {
getInstance().getBlocksPlugins().add(plugin);
}
private static void discoverPlugins(String baseDir,
List<String> blocksPlugins, List<String> pluginFactories) {
List<URL> urls = new ArrayList<>();
File pluginDir = new File(Paths.getPluginsDirectory());
if (pluginDir.exists()) {
for (File jar : pluginDir.listFiles()) {
if (jar.getName().endsWith(".jar")) {
try {
URL url = jar.toURI().toURL();
urls.add(url);
URL jarURL = new URL("jar:" + url.toString() + "!/");
JarURLConnection jarConnection = (JarURLConnection) jarURL.openConnection();
Manifest manifest = jarConnection.getManifest();
String plugins = manifest.getMainAttributes().getValue("BlocksPlugins");
if (plugins != null) {
for (StringTokenizer st = new StringTokenizer(plugins, ","); st.hasMoreTokens();) {
String plugin = st.nextToken();
blocksPlugins.add(plugin);
//System.out.println("BLock Plugin = "+plugin);
}
}
String factories = manifest.getMainAttributes().getValue("PluginFactories");
if (factories != null) {
for (StringTokenizer st = new StringTokenizer(factories, ","); st.hasMoreTokens();) {
String factory = st.nextToken();
pluginFactories.add(factory);
//System.out.println("Plugin Factory = "+factory);
}
}
} catch (IOException e) {
log.log(Level.WARNING, "plugins failed!", e);
e.printStackTrace();
}
}
}
}
// instantiate plugins
URLClassLoader modLoader = new URLClassLoader(urls.toArray(new URL[0]), StarMadeLogic.class.getClassLoader());
getInstance().setModLoader(modLoader);
}
public static List<IBlocksPlugin> getAllBlocksPlugins() {
List<IBlocksPlugin> plugins = new ArrayList<>();
plugins.addAll(getInstance().getBlocksPlugins());
for (IStarMadePluginFactory factory : getInstance().getPluginFactories()) {
IStarMadePlugin[] plugs = factory.getPlugins();
if (plugins != null) {
} else {
continue;
}
for (IStarMadePlugin plugin : plugs) {
if (plugin instanceof IBlocksPlugin) {
plugins.add((IBlocksPlugin) plugin);
}
}
}
return plugins;
}
public static List<IBlocksPlugin> getBlocksPlugins(int type, int subtype) {
List<IBlocksPlugin> plugins = new ArrayList<>();
for (IBlocksPlugin plugin : getAllBlocksPlugins()) {
if (isPlugin(plugin, type, subtype)) {
plugins.add(plugin);
}
}
return plugins;
}
private static boolean isPlugin(IStarMadePlugin plugin, int type, int subtype) {
try { // lets be protective against badly written plugins
for (int[] classification : plugin.getClassifications()) {
if ((type == IBlocksPlugin.TYPE_ALL) || (IBlocksPlugin.TYPE_ALL == classification[0]) || (type == classification[0])) {
if ((subtype == -1) || (subtype == classification[1])) {
return true;
}
}
}
} catch (Exception e) {
log.log(Level.WARNING, "plugins failed!", e);
e.printStackTrace();
}
return false;
}
public static boolean isStarMadeDirectory(String dir) {
File d = new File(dir);
if (!d.exists()) {
return false;
}
File smJar = new File(d, "StarMade.jar");
return smJar.exists();
}
public static Properties getProps() {
if (getInstance().getProps() == null) {
Properties p = new Properties();
File home = new File(System.getProperty("user.home"));
File props = new File(home, ".josm");
if (props.exists()) {
try {
try (FileInputStream fis = new FileInputStream(props)) {
p.load(fis);
}
} catch (IOException e) {
log.log(Level.WARNING, "props failed!", e);
}
}
getInstance().setProps(p);
}
return getInstance().getProps();
}
public static void saveProps() {
if (getInstance().getProps() == null) {
return;
}
File home = new File(System.getProperty("user.home"));
File props = new File(home, ".josm");
try {
try (FileWriter fos = new FileWriter(props)) {
getInstance().getProps().store(fos, "StarMade Utils defaults");
}
} catch (IOException e) {
log.log(Level.WARNING, "saveProps failed!", e);
}
}
public static String getProperty(String key) {
return getProps().getProperty(key);
}
public static boolean isProperty(String key) {
return BooleanUtils.parseBoolean(getProperty(key));
}
public static void setProperty(String key, String value) {
getProps().setProperty(key, value);
saveProps();
}
public static void setProperty(String key, boolean value) {
setProperty(key, String.valueOf(value));
}
public static boolean isClassification(int class1, int class2) {
return ((class1 == IBlocksPlugin.TYPE_ALL) || (class1 == class2));
}
public static SparseMatrix<Block> getModel() {
return getInstance().getModel();
}
public static void setModel(SparseMatrix<Block> model) {
getInstance().setModel(model);
}
}