summaryrefslogtreecommitdiff
path: root/src/main/java/com/c2kernel/process
diff options
context:
space:
mode:
authorogattaz <olivier@gattaz.com>2014-07-07 10:59:14 +0200
committerogattaz <olivier@gattaz.com>2014-07-07 10:59:14 +0200
commit6772bfb46b72d859c316a9f6573d0c6be477ad5c (patch)
treedafa343584216685e68b6edae37570eb97cf9d0c /src/main/java/com/c2kernel/process
parent2fd193d7936084de91eae46e8c2763914d87ab71 (diff)
parent0b689a787288f5a4ba568157905c3a0577f83821 (diff)
Merge branch 'master' of ssh://dev.cccs.uwe.ac.uk:22/var/git/cristal-kernel
Diffstat (limited to 'src/main/java/com/c2kernel/process')
-rw-r--r--src/main/java/com/c2kernel/process/AbstractMain.java19
-rw-r--r--src/main/java/com/c2kernel/process/Bootstrap.java43
-rw-r--r--src/main/java/com/c2kernel/process/ClientShell.java2
-rw-r--r--src/main/java/com/c2kernel/process/Gateway.java42
-rw-r--r--src/main/java/com/c2kernel/process/ShutdownHandler.java6
-rw-r--r--src/main/java/com/c2kernel/process/StandardClient.java5
-rw-r--r--src/main/java/com/c2kernel/process/StandardServer.java91
-rw-r--r--src/main/java/com/c2kernel/process/auth/Authenticator.java71
-rw-r--r--src/main/java/com/c2kernel/process/auth/ProxyLogin.java15
-rw-r--r--src/main/java/com/c2kernel/process/module/Module.java3
10 files changed, 176 insertions, 121 deletions
diff --git a/src/main/java/com/c2kernel/process/AbstractMain.java b/src/main/java/com/c2kernel/process/AbstractMain.java
index e241ee2..202ae9e 100644
--- a/src/main/java/com/c2kernel/process/AbstractMain.java
+++ b/src/main/java/com/c2kernel/process/AbstractMain.java
@@ -28,7 +28,8 @@ import com.c2kernel.utils.Logger;
**************************************************************************/
abstract public class AbstractMain
{
- public static boolean runningAsWrapper = false;
+ public static boolean isServer = false;
+ private static ShutdownHandler shutdownHandler;
/**************************************************************************
@@ -112,5 +113,19 @@ abstract public class AbstractMain
return c2kProps;
}
-
+
+ public static void setShutdownHandler(ShutdownHandler handler) {
+ shutdownHandler = handler;
+ }
+
+ public static void shutdown(int errCode) {
+ if (shutdownHandler!= null)
+ shutdownHandler.shutdown(errCode, isServer);
+ else
+ try {
+ Gateway.close();
+ } catch (Exception ex) {
+ Logger.error(ex);
+ }
+ }
}
diff --git a/src/main/java/com/c2kernel/process/Bootstrap.java b/src/main/java/com/c2kernel/process/Bootstrap.java
index bcc5e68..bc93676 100644
--- a/src/main/java/com/c2kernel/process/Bootstrap.java
+++ b/src/main/java/com/c2kernel/process/Bootstrap.java
@@ -9,6 +9,7 @@ import java.util.StringTokenizer;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.XMLUnit;
+import com.c2kernel.common.InvalidDataException;
import com.c2kernel.common.ObjectNotFoundException;
import com.c2kernel.entity.proxy.AgentProxy;
import com.c2kernel.entity.proxy.ItemProxy;
@@ -17,17 +18,17 @@ import com.c2kernel.events.History;
import com.c2kernel.lifecycle.CompositeActivityDef;
import com.c2kernel.lifecycle.instance.CompositeActivity;
import com.c2kernel.lifecycle.instance.Workflow;
-import com.c2kernel.lifecycle.instance.predefined.PredefinedStepContainer;
-import com.c2kernel.lifecycle.instance.predefined.ServerPredefinedStepContainer;
+import com.c2kernel.lifecycle.instance.predefined.server.ServerPredefinedStepContainer;
import com.c2kernel.lifecycle.instance.stateMachine.Transition;
import com.c2kernel.lookup.AgentPath;
import com.c2kernel.lookup.DomainPath;
import com.c2kernel.lookup.ItemPath;
-import com.c2kernel.lookup.Lookup;
+import com.c2kernel.lookup.LookupManager;
import com.c2kernel.lookup.Path;
import com.c2kernel.lookup.RolePath;
import com.c2kernel.persistency.ClusterStorage;
import com.c2kernel.persistency.outcome.Outcome;
+import com.c2kernel.persistency.outcome.OutcomeValidator;
import com.c2kernel.persistency.outcome.Viewpoint;
import com.c2kernel.process.resource.DefaultResourceImportHandler;
import com.c2kernel.process.resource.ResourceImportHandler;
@@ -116,6 +117,7 @@ public class Bootstrap
public static DomainPath verifyResource(String ns, String itemName, Integer version, String itemType, String dataLocation, int layer, boolean reset) throws Exception {
if (version == null) version = 0;
+ LookupManager lookupManager = Gateway.getLookupManager();
ResourceImportHandler typeImpHandler = getHandler(itemType);
Logger.msg(1, "Bootstrap.verifyResource() - Verifying version "+version+" of "+typeImpHandler.getName()+" "+itemName);
@@ -162,8 +164,8 @@ public class Bootstrap
Logger.msg("Module item "+itemName+" found with path "+path.toString()+". Moving to "+modDomPath.toString());
modDomPath.setEntity(new ItemPath(thisProxy.getSystemKey()));
if (!modDomPath.exists())
- Gateway.getLookup().add(modDomPath);
- Gateway.getLookup().delete(path);
+ lookupManager.add(modDomPath);
+ lookupManager.delete(path);
}
}
@@ -193,6 +195,15 @@ public class Bootstrap
}
// data was missing or doesn't match
+ // validate it
+ OutcomeValidator validator = OutcomeValidator.getValidator(LocalObjectLoader.getSchema(newOutcome.getSchemaType(), newOutcome.getSchemaVersion()));
+ String error = validator.validate(newOutcome.getData());
+ if (error.length() > 0) {
+ Logger.error("Outcome not valid: \n " + error);
+ throw new InvalidDataException(error, "");
+ }
+
+ // store
Logger.msg("Bootstrap.verifyResource() - Writing new "+newOutcome.getSchemaType()+" v"+version+" to "+typeImpHandler.getName()+" "+itemName);
History hist = new History(thisProxy.getSystemKey(), thisProxy);
Transition predefDone = new Transition(0, "Done", 0, 0);
@@ -242,6 +253,8 @@ public class Bootstrap
// create props
PropertyDescriptionList pdList = impHandler.getPropDesc();
PropertyArrayList props = new PropertyArrayList();
+ LookupManager lookupManager = Gateway.getLookupManager();
+
for (int i = 0; i < pdList.list.size(); i++) {
PropertyDescription pd = pdList.list.get(i);
String propName = pd.getName();
@@ -265,10 +278,10 @@ public class Bootstrap
ItemPath entityPath = Gateway.getNextKeyManager().generateNextEntityKey();
Gateway.getCorbaServer().createEntity(entityPath);
- Gateway.getLookup().add(entityPath);
+ lookupManager.add(entityPath);
DomainPath newDomPath = impHandler.getPath(itemName, ns);
newDomPath.setEntity(entityPath);
- Gateway.getLookup().add(newDomPath);
+ lookupManager.add(newDomPath);
ItemProxy newItemProxy = Gateway.getProxyManager().getProxy(entityPath);
newItemProxy.initialise( 1, props, ca, null);
return newItemProxy;
@@ -279,12 +292,14 @@ public class Bootstrap
**************************************************************************/
private static void checkAgent(String name, String pass, String role, boolean joblist) throws Exception {
Logger.msg(1, "Bootstrap.checkAgent() - Checking for existence of '"+name+"' user.");
- Lookup lookup = Gateway.getLookup();
+ LookupManager lookup = Gateway.getLookupManager();
+
try {
systemAgents.put(name, Gateway.getProxyManager().getAgentProxy(lookup.getAgentPath(name)));
Logger.msg(3, "Bootstrap.checkAgent() - User '"+name+"' found.");
return;
} catch (ObjectNotFoundException ex) { }
+
Logger.msg("Bootstrap.checkAgent() - User '"+name+"' not found. Creating.");
RolePath rolePath;
@@ -299,7 +314,7 @@ public class Bootstrap
AgentPath agentPath = new AgentPath(entityPath.getSysKey(), name);
agentPath.setPassword(pass);
Gateway.getCorbaServer().createEntity(agentPath);
- Gateway.getLookup().add(agentPath);
+ lookup.add(agentPath);
// assign admin role
Logger.msg("Bootstrap.checkAgent() - Assigning role '"+role+"'");
@@ -331,6 +346,7 @@ public class Bootstrap
}
public static void createServerItem() throws Exception {
+ LookupManager lookupManager = Gateway.getLookupManager();
String serverName = Gateway.getProperties().getProperty("ItemServer.name");
thisServerPath = new DomainPath("/servers/"+serverName);
ItemPath serverEntity;
@@ -340,9 +356,9 @@ public class Bootstrap
Logger.msg("Creating server item "+thisServerPath);
serverEntity = Gateway.getNextKeyManager().generateNextEntityKey();
Gateway.getCorbaServer().createEntity(serverEntity);
- Gateway.getLookup().add(serverEntity);
+ lookupManager.add(serverEntity);
thisServerPath.setEntity(serverEntity);
- Gateway.getLookup().add(thisServerPath);
+ lookupManager.add(thisServerPath);
}
Gateway.getStorage().put(serverEntity.getSysKey(), new Property("Name", serverName, false), null);
Gateway.getStorage().put(serverEntity.getSysKey(), new Property("Type", "Server", false), null);
@@ -358,10 +374,7 @@ public class Bootstrap
public static void initServerItemWf() throws Exception {
CompositeActivityDef serverWfCa = (CompositeActivityDef)LocalObjectLoader.getActDef("ServerItemWorkflow", 0);
- Workflow wf = new Workflow((CompositeActivity)serverWfCa.instantiate());
- PredefinedStepContainer predef = (PredefinedStepContainer)wf.search("workflow/predefined");
- wf.getChildGraphModel().removeVertex(predef);
- wf.addChild(new ServerPredefinedStepContainer(), predef.getCentrePoint());
+ Workflow wf = new Workflow((CompositeActivity)serverWfCa.instantiate(), new ServerPredefinedStepContainer());
wf.initialise(thisServerPath.getSysKey(), systemAgents.get("system").getPath());
Gateway.getStorage().put(thisServerPath.getSysKey(), wf, null);
}
diff --git a/src/main/java/com/c2kernel/process/ClientShell.java b/src/main/java/com/c2kernel/process/ClientShell.java
index b6afb2c..9f1d3ab 100644
--- a/src/main/java/com/c2kernel/process/ClientShell.java
+++ b/src/main/java/com/c2kernel/process/ClientShell.java
@@ -33,7 +33,7 @@ public class ClientShell extends StandardClient {
}
System.out.print("> ");
}
- close();
+ shutdown(0);
}
public static void main(String[] args) throws Exception {
diff --git a/src/main/java/com/c2kernel/process/Gateway.java b/src/main/java/com/c2kernel/process/Gateway.java
index 2db7aa1..7a040ac 100644
--- a/src/main/java/com/c2kernel/process/Gateway.java
+++ b/src/main/java/com/c2kernel/process/Gateway.java
@@ -9,6 +9,7 @@ import java.net.MalformedURLException;
import java.util.Enumeration;
import java.util.Properties;
+import com.c2kernel.common.CannotManageException;
import com.c2kernel.common.InvalidDataException;
import com.c2kernel.common.ObjectNotFoundException;
import com.c2kernel.entity.CorbaServer;
@@ -17,6 +18,7 @@ import com.c2kernel.entity.proxy.ProxyManager;
import com.c2kernel.entity.proxy.ProxyServer;
import com.c2kernel.lookup.AgentPath;
import com.c2kernel.lookup.Lookup;
+import com.c2kernel.lookup.LookupManager;
import com.c2kernel.persistency.ClusterStorageException;
import com.c2kernel.persistency.NextKeyManager;
import com.c2kernel.persistency.TransactionManager;
@@ -58,6 +60,7 @@ public class Gateway
static private org.omg.CORBA.ORB mORB;
static private boolean orbDestroyed = false;
static private Lookup mLookup;
+ static private LookupManager mLookupManager = null;
static private NextKeyManager mNextKeyManager;
static private TransactionManager mStorage;
static private ProxyManager mProxyManager;
@@ -111,7 +114,7 @@ public class Gateway
// init module manager
try {
- mModules = new ModuleManager(mResource.getModuleDefURLs(), AbstractMain.runningAsWrapper);
+ mModules = new ModuleManager(mResource.getModuleDefURLs(), AbstractMain.isServer);
} catch (Exception e) {
Logger.error(e);
throw new InvalidDataException("Could not load module definitions.", "");
@@ -145,13 +148,20 @@ public class Gateway
*
* @throws InvalidDataException - error initialising
*/
- static public void startServer() throws InvalidDataException {
+ static public void startServer(Authenticator auth) throws InvalidDataException, CannotManageException {
try {
// check top level directory contexts
- mLookup.initializeDirectory();
+ if (mLookup instanceof LookupManager) {
+ mLookupManager = (LookupManager)mLookup;
+ mLookupManager.initializeDirectory();
+ }
+ else {
+ throw new CannotManageException("Lookup implementation is not a LookupManager. Cannot write to directory");
+ }
// init next key manager
mNextKeyManager = (NextKeyManager)mC2KProps.getInstance("NextKeyManager");
+ mNextKeyManager.open(auth);
// start entity proxy server
mProxyServer = new ProxyServer(mC2KProps.getProperty("ItemServer.name"));
@@ -165,7 +175,8 @@ public class Gateway
//TODO: externalize this (or replace corba completely)
mC2KProps.put("com.sun.CORBA.POA.ORBServerId", "1");
mC2KProps.put("com.sun.CORBA.POA.ORBPersistentServerPort", serverPort);
-
+ mC2KProps.put("com.sun.CORBA.codeset.charsets", "0x05010001, 0x00010109"); // need to force UTF-8 in the Sun ORB
+ mC2KProps.put("com.sun.CORBA.codeset.wcharsets", "0x00010109, 0x05010001");
//Standard initialisation of the ORB
mORB = org.omg.CORBA.ORB.init(new String[0], mC2KProps);
@@ -196,7 +207,7 @@ public class Gateway
* @throws InvalidDataException - bad params
* @throws ClusterStorageException - error starting storages
*/
- static public void connect()
+ static public Authenticator connect()
throws InvalidDataException,
ClusterStorageException
{
@@ -210,6 +221,7 @@ public class Gateway
mStorage = new TransactionManager(auth);
mProxyManager = new ProxyManager();
+ return auth;
} catch (Exception ex) {
Logger.error(ex);
throw new InvalidDataException("Cannot connect server process. Please check config.", "");
@@ -254,6 +266,12 @@ public class Gateway
return userProxy;
}
+
+ static public AgentProxy connect(String agentName, String agentPassword)
+ throws InvalidDataException, ObjectNotFoundException, ClusterStorageException, InstantiationException, IllegalAccessException, ClassNotFoundException
+ {
+ return connect(agentName, agentPassword, null);
+ }
/**
* Shuts down all kernel api objects
@@ -299,8 +317,12 @@ public class Gateway
static public org.omg.CORBA.ORB getORB()
{
if (orbDestroyed) throw new RuntimeException("Gateway has been closed. ORB is destroyed.");
- if (mORB == null)
+
+ if (mORB == null) {
+ mC2KProps.put("com.sun.CORBA.codeset.charsets", "0x05010001, 0x00010109"); // need to force UTF-8 in the Sun ORB
+ mC2KProps.put("com.sun.CORBA.codeset.wcharsets", "0x00010109, 0x05010001");
mORB = org.omg.CORBA.ORB.init(new String[0], mC2KProps);
+ }
return mORB;
}
@@ -309,6 +331,14 @@ public class Gateway
return mLookup;
}
+ static public LookupManager getLookupManager() throws CannotManageException
+ {
+ if (mLookupManager == null)
+ throw new CannotManageException("No Lookup Manager created. Not a server process.", "");
+ else
+ return mLookupManager;
+ }
+
static public CorbaServer getCorbaServer()
{
return mCorbaServer;
diff --git a/src/main/java/com/c2kernel/process/ShutdownHandler.java b/src/main/java/com/c2kernel/process/ShutdownHandler.java
new file mode 100644
index 0000000..aaed899
--- /dev/null
+++ b/src/main/java/com/c2kernel/process/ShutdownHandler.java
@@ -0,0 +1,6 @@
+package com.c2kernel.process;
+
+public interface ShutdownHandler {
+
+ public void shutdown(int errCode, boolean isServer);
+}
diff --git a/src/main/java/com/c2kernel/process/StandardClient.java b/src/main/java/com/c2kernel/process/StandardClient.java
index 5978068..d2b58a5 100644
--- a/src/main/java/com/c2kernel/process/StandardClient.java
+++ b/src/main/java/com/c2kernel/process/StandardClient.java
@@ -18,9 +18,4 @@ abstract public class StandardClient extends AbstractMain
Gateway.init(readC2KArgs(args));
//AgentProxy user = Gateway.connect("username", "password");
}
-
- static public void close() {
- Gateway.close();
- }
-
}
diff --git a/src/main/java/com/c2kernel/process/StandardServer.java b/src/main/java/com/c2kernel/process/StandardServer.java
index e283cb6..5855d7e 100644
--- a/src/main/java/com/c2kernel/process/StandardServer.java
+++ b/src/main/java/com/c2kernel/process/StandardServer.java
@@ -10,9 +10,7 @@
package com.c2kernel.process;
-import org.tanukisoftware.wrapper.WrapperListener;
-import org.tanukisoftware.wrapper.WrapperManager;
-
+import com.c2kernel.process.auth.Authenticator;
import com.c2kernel.utils.Logger;
/**************************************************************************
@@ -21,108 +19,39 @@ import com.c2kernel.utils.Logger;
* @author $Author: abranson $ $Date: 2005/04/28 13:49:43 $
* @version $Revision: 1.47 $
**************************************************************************/
-public class StandardServer extends AbstractMain implements WrapperListener
+public class StandardServer extends AbstractMain
{
protected static StandardServer server;
-
- /**************************************************************************
- * C2KRootPOA suitable for Factory objects
- **************************************************************************/
-
-
-
-
-
/**************************************************************************
* void StandardInitalisation( String[] )
*
* Set-up calls to ORB, POA and Factorys, both optional and required.
**************************************************************************/
- protected void standardInitialisation( String[] args )
+ protected static void standardInitialisation( String[] args )
throws Exception
{
+ isServer = true;
+
// read args and init Gateway
Gateway.init(readC2KArgs(args));
// connect to LDAP as root
- Gateway.connect();
+ Authenticator auth = Gateway.connect();
//start console
Logger.initConsole("ItemServer");
//initialize the server objects
- Gateway.startServer();
+ Gateway.startServer(auth);
Logger.msg(5, "StandardServer::standardInitialisation - complete.");
}
-
- /**************************************************************************
- * Sets up and runs and item server
- **************************************************************************/
- @Override
- public Integer start(String[] args)
+ public static void main(String[] args) throws Exception
{
- try
- {
- //initialise everything
- standardInitialisation( args );
- }
- catch( Exception ex )
- {
- ex.printStackTrace();
- Logger.die("Startup failed");
- }
- return null;
- }
-
- public static void main(String[] args) {
- AbstractMain.runningAsWrapper = true;
- server = new StandardServer();
- WrapperManager.start( server, args );
- }
-
- /**
- *
- */
- @Override
- public void controlEvent(int event) {
- if (WrapperManager.isControlledByNativeWrapper()) {
- // The Wrapper will take care of this event
- } else {
- // We are not being controlled by the Wrapper, so
- // handle the event ourselves.
- if ((event == WrapperManager.WRAPPER_CTRL_C_EVENT) ||
- (event == WrapperManager.WRAPPER_CTRL_CLOSE_EVENT) ||
- (event == WrapperManager.WRAPPER_CTRL_SHUTDOWN_EVENT)){
- WrapperManager.stop(0);
- }
- }
-
+ //initialise everything
+ standardInitialisation( args );
}
-
- /**************************************************************************
- * Closes all listeners, quits the VM.
- * This method should be called to kill the server process
- * e.g. from the NT service wrapper
- **************************************************************************/
- @Override
- public int stop(int arg0) {
- WrapperManager.signalStopping(10000);
- try
- {
- Gateway.close();
- }
- catch( Exception ex )
- {
- Logger.error(ex);
- return 1;
- }
-
- Logger.msg("StandardServer::shutdown - complete. ");
- return 0;
- }
-
}
diff --git a/src/main/java/com/c2kernel/process/auth/Authenticator.java b/src/main/java/com/c2kernel/process/auth/Authenticator.java
index 40defc4..44745da 100644
--- a/src/main/java/com/c2kernel/process/auth/Authenticator.java
+++ b/src/main/java/com/c2kernel/process/auth/Authenticator.java
@@ -3,14 +3,71 @@ package com.c2kernel.process.auth;
import com.c2kernel.common.InvalidDataException;
import com.c2kernel.common.ObjectNotFoundException;
-
+/**
+ * This interface is used by the kernel to store an authenticated connection
+ * and/or token that will be used by kernel components. The CRISTAL property
+ * 'Authenticator' is used to specify the implementation used. It is
+ * instantiated by the connect() methods of the Gateway, and will be found in
+ * the AgentProxy returned by connect(). Lookup and ClusterStorage instances are
+ * initialized with this Authenticator, which is expected to maintain the same
+ * user's connection through the process lifetime, reconnecting if the
+ * connection is lost.
+ *
+ * @since 3.0
+ *
+ */
public interface Authenticator {
-
- public boolean authenticate(String agentName, String password, String resource) throws InvalidDataException, ObjectNotFoundException;
-
- public boolean authenticate(String resource) throws InvalidDataException, ObjectNotFoundException;
-
+
+ /**
+ * Authenticates a CRISTAL agent. If this method returns true, then the
+ * connect method will create and return an AgentProxy for the given
+ * username using the Lookup and ProxyManager.
+ *
+ * @param agentName
+ * The username of the Agent to be authenticated. This must be
+ * already present as an Agent in the CRISTAL directory.
+ * @param password
+ * The Agent's password
+ * @param resource
+ * The authentication resource/domain/realm of the agent.
+ * Included so that domains may include CRISTAL users from
+ * different realms. This parameter is passed into the connect()
+ * method if required. May be null.
+ * @return a boolean indicating if the authentication was successful. If so,
+ * then the Gateway will generate an AgentProxy for the given user.
+ * @throws ObjectNotFoundException
+ * When the Agent doesn't exist
+ * @throws InvalidDataException
+ * When authentication fails for another reason
+ */
+ public boolean authenticate(String agentName, String password,
+ String resource) throws InvalidDataException,
+ ObjectNotFoundException;
+
+ /**
+ * Authenticates a superuser connection for the server. It must be able to
+ * act on behalf of any other Agent, as the server needs to do this.
+ * Credentials may be in the CRISTAL properties, or some other mechanism.
+ *
+ * @param resource
+ * @return
+ * @throws InvalidDataException
+ * @throws ObjectNotFoundException
+ */
+ public boolean authenticate(String resource) throws InvalidDataException,
+ ObjectNotFoundException;
+
+ /**
+ * Lookup and storage implementations that need to use user or superuser
+ * authentication can retrieve it using this method. This will be highly
+ * implementation specific.
+ *
+ * @return the connection/token created during authentication
+ */
public Object getAuthObject();
-
+
+ /**
+ * Close or expire the connection as the CRISTAL process shuts down.
+ */
public void disconnect();
}
diff --git a/src/main/java/com/c2kernel/process/auth/ProxyLogin.java b/src/main/java/com/c2kernel/process/auth/ProxyLogin.java
index 94416cf..665158c 100644
--- a/src/main/java/com/c2kernel/process/auth/ProxyLogin.java
+++ b/src/main/java/com/c2kernel/process/auth/ProxyLogin.java
@@ -4,9 +4,18 @@ import java.util.Properties;
import com.c2kernel.entity.proxy.AgentProxy;
+/**
+ * This interface is used by client processes to implement alternative login
+ * mechanisms aside from the standard username and password. Implementations may
+ * synchronize Agents with an external user library, such as Active Directory.
+ * Implementations are expected to set up the Gateway process and its
+ * authenticated components itself.
+ *
+ */
public interface ProxyLogin {
- public void initialize(Properties props) throws Exception;
- public AgentProxy authenticate(String resource) throws Exception;
-
+ public void initialize(Properties props) throws Exception;
+
+ public AgentProxy authenticate(String resource) throws Exception;
+
}
diff --git a/src/main/java/com/c2kernel/process/module/Module.java b/src/main/java/com/c2kernel/process/module/Module.java
index 873754f..195c883 100644
--- a/src/main/java/com/c2kernel/process/module/Module.java
+++ b/src/main/java/com/c2kernel/process/module/Module.java
@@ -84,6 +84,7 @@ public class Module {
thisRes.resourceType, thisRes.resourceLocation, info.layer, reset);
} catch (Exception ex) {
Logger.error(ex);
+ Logger.die("Error importing module resources. Unsafe to continue.");
}
}
@@ -148,4 +149,4 @@ public class Module {
public boolean hasDependency(String dep) {
return info.dependency.contains(dep);
}
-} \ No newline at end of file
+}