Initial commit from SVN.
This commit is contained in:
9
Foundation Web Server Shared/.classpath
Normal file
9
Foundation Web Server Shared/.classpath
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/Common"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/Foundation"/>
|
||||
<classpathentry combineaccessrules="false" exported="true" kind="src" path="/Foundation Web Interfaces"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
17
Foundation Web Server Shared/.project
Normal file
17
Foundation Web Server Shared/.project
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Foundation Web Server Shared</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.foundation.web.server.shared;
|
||||
|
||||
import com.foundation.util.IManagedList;
|
||||
|
||||
public interface IWebServer {
|
||||
/**
|
||||
* Gets the web application metadata.
|
||||
* @return The list of webapp bundle metadata. A webapp bundle is a zip containing one or more webapps. The list contains instances of WebappBundle.
|
||||
*/
|
||||
public IManagedList getWebappBundles();
|
||||
/**
|
||||
* Refreshes the bundle by unpacking the lastest webapp zip and stopping and starting the webapp.
|
||||
* @param bundleName The name of the app bundle to refresh.
|
||||
*/
|
||||
public void refreshWebapp(String bundleName);
|
||||
/**
|
||||
* Reloads the bundle (stop & starts it) without unpacking the latest webapp zip.
|
||||
* @param bundleName The name of the app bundle to reload.
|
||||
*/
|
||||
public void reloadWebapp(String bundleName);
|
||||
/**
|
||||
* Permenantly removes the webapp files and archive from the disk and server. Does not remove external files or external settings/configurations.
|
||||
* @param bundleName The name of the app bundle to remove.
|
||||
*/
|
||||
public void removeWebapp(String bundleName);
|
||||
/**
|
||||
* Searches for new or missing web applications in the archive path and updates the app path and loads or unloads new or missing webapps.
|
||||
* @param archivePath The path containing the web application archives, one zip per web application.
|
||||
* @param appPath The path where the archive for each web app should be unpacked and utilized.
|
||||
*/
|
||||
public void refreshWebapps();
|
||||
/**
|
||||
* Shuts the web server down.
|
||||
*/
|
||||
public void shutdown();
|
||||
}//IWebServerProxy//
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.foundation.web.server.shared;
|
||||
/**
|
||||
* An object that allows the web server to connect to the monitor application.
|
||||
*/
|
||||
public interface IWebServerMonitorConnection {
|
||||
public static final String ORB_NAME = "WebServerMonitorConnection";
|
||||
/**
|
||||
* Sets the connector the monitor process will use to manage and interact with the web server.
|
||||
* @param connector The connector used to interact.
|
||||
*/
|
||||
public void setConnector(IWebServer connector);
|
||||
}//IWebServerMonitorConnection//
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.foundation.web.server.shared.model;
|
||||
|
||||
import com.foundation.application.IApplication;
|
||||
import com.foundation.model.Model;
|
||||
|
||||
public abstract class AbstractModel extends Model {
|
||||
/**
|
||||
* AbstractModel constructor.
|
||||
*/
|
||||
public AbstractModel() {
|
||||
}//AbstractModel()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.common.Entity#getApplication()
|
||||
*/
|
||||
public IApplication getApplication() {
|
||||
return null;
|
||||
}//getApplication()//
|
||||
}//AbstractModel//
|
||||
@@ -0,0 +1,186 @@
|
||||
package com.foundation.web.server.shared.model;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.common.orb.Orb;
|
||||
import com.foundation.common.AttributeBinding;
|
||||
import com.foundation.common.IEntity.ICalculatedAttributeListener;
|
||||
import com.foundation.event.model.IModelListenerAttributeHandler;
|
||||
import com.foundation.event.model.ModelListener;
|
||||
import com.foundation.metadata.Attribute;
|
||||
|
||||
/**
|
||||
* Abstracts the webapp log reference for the web server and each web application.
|
||||
*/
|
||||
public abstract class BaseApp extends AbstractModel {
|
||||
public static final Attribute LOG = registerAttribute(BaseApp.class, "log", AO_REFERENCED | AO_REFLECT_AS_IMMUTABLE);
|
||||
public static final Attribute ERROR_COUNT = registerAttribute(BaseApp.class, "errorCount", new Integer(0));
|
||||
public static final Attribute WARNING_COUNT = registerAttribute(BaseApp.class, "warningCount", new Integer(0));
|
||||
public static final Attribute INFO_COUNT = registerAttribute(BaseApp.class, "infoCount", new Integer(0));
|
||||
public static final Attribute ERROR_CHANGE_FLAG = registerAttribute(BaseApp.class, "errorChangeFlag", AO_REFERENCED | AO_NO_REFLECT | AO_TRANSIENT | AO_CALCULATED, Boolean.FALSE);
|
||||
public static final Attribute WARNING_CHANGE_FLAG = registerAttribute(BaseApp.class, "warningChangeFlag", AO_REFERENCED | AO_NO_REFLECT | AO_TRANSIENT | AO_CALCULATED, Boolean.FALSE);
|
||||
public static final Attribute INFO_CHANGE_FLAG = registerAttribute(BaseApp.class, "infoChangeFlag", AO_REFERENCED | AO_NO_REFLECT | AO_TRANSIENT | AO_CALCULATED, Boolean.FALSE);
|
||||
/**
|
||||
* BaseApp constructor.
|
||||
*/
|
||||
public BaseApp() {
|
||||
}//BaseApp()//
|
||||
/**
|
||||
* BaseApp constructor.
|
||||
*/
|
||||
public BaseApp(String name, File storagePath) throws IOException {
|
||||
setLog(new WebappLog(storagePath, name));
|
||||
}//BaseApp()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.common.Entity#calculatedAttributeRegister(com.foundation.metadata.Attribute, com.foundation.common.IEntity.ICalculatedAttributeListener)
|
||||
*/
|
||||
protected ModelListener calculatedAttributeRegister(Attribute attribute, ICalculatedAttributeListener listener) {
|
||||
ModelListener result;
|
||||
|
||||
if(attribute == ERROR_CHANGE_FLAG) {
|
||||
result = new ModelListener(this);
|
||||
result.addBinding(new AttributeBinding(BaseApp.class, BaseApp.ERROR_COUNT, AttributeBinding.FLAG_LAZY_LOAD_ATTRIBUTE, listener, null));
|
||||
}//if//
|
||||
else if(attribute == WARNING_CHANGE_FLAG) {
|
||||
result = new ModelListener(this);
|
||||
result.addBinding(new AttributeBinding(BaseApp.class, BaseApp.WARNING_COUNT, AttributeBinding.FLAG_LAZY_LOAD_ATTRIBUTE, listener, null));
|
||||
}//else if//
|
||||
else if(attribute == INFO_CHANGE_FLAG) {
|
||||
result = new ModelListener(this);
|
||||
result.addBinding(new AttributeBinding(BaseApp.class, BaseApp.INFO_COUNT, AttributeBinding.FLAG_LAZY_LOAD_ATTRIBUTE, listener, null));
|
||||
}//else if//
|
||||
else {
|
||||
result = super.calculatedAttributeRegister(attribute, listener);
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//calculatedAttributeRegister()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.common.Entity#calculatedAttributeUpdate(com.foundation.metadata.Attribute)
|
||||
*/
|
||||
protected Object calculatedAttributeUpdate(Attribute attribute) {
|
||||
Object result = null;
|
||||
|
||||
if(attribute == ERROR_CHANGE_FLAG) {
|
||||
result = getErrorChangeFlag() == null || !getErrorChangeFlag().booleanValue() ? Boolean.TRUE : Boolean.FALSE;
|
||||
}//if//
|
||||
else if(attribute == WARNING_CHANGE_FLAG) {
|
||||
result = getWarningChangeFlag() == null || !getWarningChangeFlag().booleanValue() ? Boolean.TRUE : Boolean.FALSE;
|
||||
}//else if//
|
||||
else if(attribute == INFO_CHANGE_FLAG) {
|
||||
result = getInfoChangeFlag() == null || !getInfoChangeFlag().booleanValue() ? Boolean.TRUE : Boolean.FALSE;
|
||||
}//else if//
|
||||
else {
|
||||
result = super.calculatedAttributeUpdate(attribute);
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//calculatedAttributeUpdate()//
|
||||
/**
|
||||
* Resets the log count change flags.
|
||||
*/
|
||||
public void resetLogCountChangeFlags() {
|
||||
setErrorChangeFlag(Boolean.FALSE);
|
||||
setWarningChangeFlag(Boolean.FALSE);
|
||||
setInfoChangeFlag(Boolean.FALSE);
|
||||
}//resetLogCountChangeFlags()//
|
||||
/**
|
||||
* Gets the log value.
|
||||
* @return The log value.
|
||||
*/
|
||||
public IWebappLog getLog() {
|
||||
return (IWebappLog) getAttributeValue(LOG);
|
||||
}//getLog()//
|
||||
/**
|
||||
* Sets the log value.
|
||||
* @param log The log which will be proxied such that remote processes have access to the log without reflecting.
|
||||
*/
|
||||
protected void setLog(IWebappLog log) {
|
||||
setAttributeValue(LOG, Orb.isProxy(log) ? log : Orb.getProxy(log, IWebappLog.class));
|
||||
}//setLog()//
|
||||
/**
|
||||
* Gets the errorCount value.
|
||||
* @return The errorCount value.
|
||||
*/
|
||||
public Integer getErrorCount() {
|
||||
return (Integer) getAttributeValue(ERROR_COUNT);
|
||||
}//getErrorCount()//
|
||||
/**
|
||||
* Sets the errorCount value.
|
||||
* @param errorCount The errorCount value.
|
||||
*/
|
||||
public void setErrorCount(Integer errorCount) {
|
||||
setAttributeValue(ERROR_COUNT, errorCount);
|
||||
}//setErrorCount()//
|
||||
/**
|
||||
* Gets the warningCount value.
|
||||
* @return The warningCount value.
|
||||
*/
|
||||
public Integer getWarningCount() {
|
||||
return (Integer) getAttributeValue(WARNING_COUNT);
|
||||
}//getWarningCount()//
|
||||
/**
|
||||
* Sets the warningCount value.
|
||||
* @param warningCount The warningCount value.
|
||||
*/
|
||||
public void setWarningCount(Integer warningCount) {
|
||||
setAttributeValue(WARNING_COUNT, warningCount);
|
||||
}//setWarningCount()//
|
||||
/**
|
||||
* Gets the infoCount value.
|
||||
* @return The infoCount value.
|
||||
*/
|
||||
public Integer getInfoCount() {
|
||||
return (Integer) getAttributeValue(INFO_COUNT);
|
||||
}//getInfoCount()//
|
||||
/**
|
||||
* Sets the infoCount value.
|
||||
* @param infoCount The infoCount value.
|
||||
*/
|
||||
public void setInfoCount(Integer infoCount) {
|
||||
setAttributeValue(INFO_COUNT, infoCount);
|
||||
}//setInfoCount()//
|
||||
/**
|
||||
* Gets the errorChangeFlag value.
|
||||
* @return The errorChangeFlag value.
|
||||
*/
|
||||
public Boolean getErrorChangeFlag() {
|
||||
return (Boolean) getAttributeValue(ERROR_CHANGE_FLAG);
|
||||
}//getErrorChangeFlag()//
|
||||
/**
|
||||
* Sets the errorChangeFlag value.
|
||||
* @param errorChangeFlag The errorChangeFlag value.
|
||||
*/
|
||||
private void setErrorChangeFlag(Boolean errorChangeFlag) {
|
||||
setAttributeValue(ERROR_CHANGE_FLAG, errorChangeFlag);
|
||||
}//setErrorChangeFlag()//
|
||||
/**
|
||||
* Gets the warningChangeFlag value.
|
||||
* @return The warningChangeFlag value.
|
||||
*/
|
||||
public Boolean getWarningChangeFlag() {
|
||||
return (Boolean) getAttributeValue(WARNING_CHANGE_FLAG);
|
||||
}//getWarningChangeFlag()//
|
||||
/**
|
||||
* Sets the warningChangeFlag value.
|
||||
* @param warningChangeFlag The warningChangeFlag value.
|
||||
*/
|
||||
private void setWarningChangeFlag(Boolean warningChangeFlag) {
|
||||
setAttributeValue(WARNING_CHANGE_FLAG, warningChangeFlag);
|
||||
}//setWarningChangeFlag()//
|
||||
/**
|
||||
* Gets the infoChangeFlag value.
|
||||
* @return The infoChangeFlag value.
|
||||
*/
|
||||
public Boolean getInfoChangeFlag() {
|
||||
return (Boolean) getAttributeValue(INFO_CHANGE_FLAG);
|
||||
}//getInfoChangeFlag()//
|
||||
/**
|
||||
* Sets the infoChangeFlag value.
|
||||
* @param infoChangeFlag The infoChangeFlag value.
|
||||
*/
|
||||
private void setInfoChangeFlag(Boolean infoChangeFlag) {
|
||||
setAttributeValue(INFO_CHANGE_FLAG, infoChangeFlag);
|
||||
}//setInfoChangeFlag()//
|
||||
}//BaseApp//
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.foundation.web.server.shared.model;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.foundation.model.IModel;
|
||||
|
||||
public interface IWebappLog extends IModel {
|
||||
/**
|
||||
* Gets the number of webapp log entries in the log.
|
||||
* @return The current number of entries in the log.
|
||||
*/
|
||||
public int getEntryCount();
|
||||
/**
|
||||
* Retrieves a range of log entries.
|
||||
* @param index The zero based index of the first log entry to be retrieved (the oldest entry of those being retrieved). Note that log entries that are more recent have a higher index. The log entry at index zero is the very first log entry.
|
||||
* @param count The count of log entries to retrieve. The last entry retrieved will be index + count.
|
||||
* @return The set of entries that was requested.
|
||||
* @throws IOException If a file IO related problem occurs.
|
||||
* @throws IllegalArgumentExceptions If the arguments are not well formed.
|
||||
*/
|
||||
public WebappLogEntry[] getEntries(int index, int count) throws IOException;
|
||||
}//IWebappLog//
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.foundation.web.server.shared.model;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Represents the web server in the views.
|
||||
*/
|
||||
public class ServerApp extends BaseApp {
|
||||
/**
|
||||
* ServerApp constructor.
|
||||
*/
|
||||
public ServerApp() {
|
||||
}//ServerApp()//
|
||||
/**
|
||||
* ServerApp constructor.
|
||||
* @param storagePath The location log files will be stored at.
|
||||
*/
|
||||
public ServerApp(File storagePath) throws IOException {
|
||||
super(null, storagePath);
|
||||
}//ServerApp()//
|
||||
/**
|
||||
* Gets the name of the app as displayed in the UI.
|
||||
* @return The UI name for this object.
|
||||
*/
|
||||
public String getName() {
|
||||
return "Server";
|
||||
}//getName()//
|
||||
}//ServerApp//
|
||||
@@ -0,0 +1,211 @@
|
||||
package com.foundation.web.server.shared.model;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.common.comparison.Comparator;
|
||||
import com.common.debug.Debug;
|
||||
import com.common.orb.Orb;
|
||||
import com.common.util.LiteHashSet;
|
||||
import com.foundation.metadata.Attribute;
|
||||
import com.foundation.util.xml.INode;
|
||||
import com.foundation.web.interfaces.IWebApplication;
|
||||
import com.foundation.web.interfaces.IWebApplicationFactory;
|
||||
|
||||
/**
|
||||
* Encapsulates information about a web application recognized by the web server.
|
||||
*/
|
||||
public class WebappBundle extends BaseApp {
|
||||
public static final Attribute NAME = registerAttribute(WebappBundle.class, "name");
|
||||
public static final Attribute ZIP_FILE = registerAttribute(WebappBundle.class, "zipFile");
|
||||
public static final Attribute BASE_DIRECTORY = registerAttribute(WebappBundle.class, "baseDirectory");
|
||||
public static final Attribute WEBAPP_CLASS_NAME = registerAttribute(WebappBundle.class, "webappClassName");
|
||||
public static final Attribute HASH = registerAttribute(WebappBundle.class, "hash");
|
||||
public static final Attribute LOADER = registerAttribute(WebappBundle.class, "loader", AO_REFERENCED | AO_REFLECT_AS_IMMUTABLE);
|
||||
public static final Attribute WEB_APPLICATIONS = registerAttribute(WebappBundle.class, "webApplications", AO_REFERENCED | AO_REFLECT_AS_IMMUTABLE);
|
||||
public static final Attribute WEB_APPLICATION_FACTORY = registerAttribute(WebappBundle.class, "webApplicationFactory", AO_REFERENCED | AO_REFLECT_AS_IMMUTABLE);
|
||||
/**
|
||||
* WebappBundle constructor.
|
||||
*/
|
||||
public WebappBundle() {
|
||||
//Required for the reflection code.//
|
||||
}//WebappBundle()//
|
||||
/**
|
||||
* WebappMetadata constructor.
|
||||
* @param name
|
||||
* @param zipFile
|
||||
* @param hash
|
||||
*/
|
||||
public WebappBundle(String name, File zipFile, String hash) {
|
||||
setName(name);
|
||||
setZipFile(zipFile);
|
||||
setHash(hash);
|
||||
}//WebappMetadata()//
|
||||
/**
|
||||
* WebappMetadata constructor.
|
||||
* @param webappNode The node containing the bundle xml for the webapp.
|
||||
*/
|
||||
public WebappBundle(INode webappNode) throws IOException {
|
||||
super();
|
||||
setName(webappNode.getAttributeValue("name"));
|
||||
setZipFile(new File(webappNode.getAttributeValue("zip-file")));
|
||||
setBaseDirectory(new File(webappNode.getAttributeValue("base-dir")));
|
||||
setWebappClassName(webappNode.getAttributeValue("webapp-class-name"));
|
||||
setHash(webappNode.getAttributeValue("hash"));
|
||||
}//WebappMetadata()//
|
||||
/**
|
||||
* Initializes the webapp log.
|
||||
*/
|
||||
public void initializeLog() throws IOException {
|
||||
if(getLog() == null) {
|
||||
setLog(new WebappLog(getBaseDirectory(), getName()));
|
||||
}//if//
|
||||
}//initializeLog()//
|
||||
/**
|
||||
* Releases the log, allowing the log files to be deleted.
|
||||
*/
|
||||
public void releaseLog() {
|
||||
if(!isReflection() && getLog() != null) {
|
||||
((WebappLog) Orb.getLocal(getLog())).close();
|
||||
setLog(null);
|
||||
}//if//
|
||||
}//releaseLog()//
|
||||
/**
|
||||
* Writes the bundle data to xml.
|
||||
* @param webappNode The node to fill with the bundle xml.
|
||||
*/
|
||||
public void writeXml(INode webappNode) {
|
||||
webappNode.addAttribute("name", getName());
|
||||
webappNode.addAttribute("zip-file", getZipFile());
|
||||
webappNode.addAttribute("base-dir", getBaseDirectory());
|
||||
webappNode.addAttribute("webapp-class-name", getWebappClassName());
|
||||
webappNode.addAttribute("hash", getHash());
|
||||
}//writeXml()//
|
||||
/**
|
||||
* Gets the name value.
|
||||
* @return The name value.
|
||||
*/
|
||||
public String getName() {
|
||||
return (String) getAttributeValue(NAME);
|
||||
}//getName()//
|
||||
/**
|
||||
* Sets the name value.
|
||||
* @param name The name value.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
setAttributeValue(NAME, name);
|
||||
}//setName()//
|
||||
/**
|
||||
* Gets the zipFile value.
|
||||
* @return The zipFile value.
|
||||
*/
|
||||
public File getZipFile() {
|
||||
return (File) getAttributeValue(ZIP_FILE);
|
||||
}//getZipFile()//
|
||||
/**
|
||||
* Sets the zipFile value.
|
||||
* @param zipFile The zipFile value.
|
||||
*/
|
||||
public void setZipFile(File zipFile) {
|
||||
setAttributeValue(ZIP_FILE, zipFile);
|
||||
}//setZipFile()//
|
||||
/**
|
||||
* Gets the directory value.
|
||||
* @return The directory value.
|
||||
*/
|
||||
public File getBaseDirectory() {
|
||||
return (File) getAttributeValue(BASE_DIRECTORY);
|
||||
}//getBaseDirectory()//
|
||||
/**
|
||||
* Sets the directory value.
|
||||
* @param directory The directory value.
|
||||
*/
|
||||
public void setBaseDirectory(File directory) {
|
||||
setAttributeValue(BASE_DIRECTORY, directory);
|
||||
}//setBaseDirectory()//
|
||||
/**
|
||||
* Gets the loader value.
|
||||
* @return The loader value.
|
||||
*/
|
||||
public ClassLoader getLoader() {
|
||||
return (ClassLoader) getAttributeValue(LOADER);
|
||||
}//getLoader()//
|
||||
/**
|
||||
* Sets the loader value.
|
||||
* @param loader The loader value.
|
||||
*/
|
||||
public void setLoader(ClassLoader loader) {
|
||||
setAttributeValue(LOADER, loader);
|
||||
}//setLoader()//
|
||||
/**
|
||||
* Gets the webappClassName value.
|
||||
* @return The webappClassName value.
|
||||
*/
|
||||
public String getWebappClassName() {
|
||||
return (String) getAttributeValue(WEBAPP_CLASS_NAME);
|
||||
}//getWebappClassName()//
|
||||
/**
|
||||
* Sets the webappClassName value.
|
||||
* @param webappClassName The webappClassName value.
|
||||
*/
|
||||
public void setWebappClassName(String webappClassName) {
|
||||
setAttributeValue(WEBAPP_CLASS_NAME, webappClassName);
|
||||
}//setWebappClassName()//
|
||||
/**
|
||||
* Gets the hash value.
|
||||
* @return The hash value.
|
||||
*/
|
||||
public String getHash() {
|
||||
return (String) getAttributeValue(HASH);
|
||||
}//getHash()//
|
||||
/**
|
||||
* Sets the hash value.
|
||||
* @param hash The hash value.
|
||||
*/
|
||||
public void setHash(String hash) {
|
||||
setAttributeValue(HASH, hash);
|
||||
}//setHash()//
|
||||
/**
|
||||
* Gets the webApplications value.
|
||||
* @return The webApplications value.
|
||||
*/
|
||||
public IWebApplication[] getWebApplications() {
|
||||
return (IWebApplication[]) getAttributeValue(WEB_APPLICATIONS);
|
||||
}//getWebApplications()//
|
||||
/**
|
||||
* Sets the webApplications value.
|
||||
* @param webApplications The webApplications value.
|
||||
*/
|
||||
public void setWebApplications(IWebApplication[] webApplications) {
|
||||
LiteHashSet nameSet = new LiteHashSet(100, Comparator.getStringComparator(), LiteHashSet.STYLE_NO_DUPLICATES);
|
||||
|
||||
//Verify two web applications don't share the same identifying name.//
|
||||
for(int index = 0; index < webApplications.length; index++) {
|
||||
if(nameSet.add(webApplications[index].getName()) == -1) {
|
||||
Debug.log(new RuntimeException("Cannot add two web applications with the same identifying name."));
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
setAttributeValue(WEB_APPLICATIONS, webApplications);
|
||||
}//setWebApplications()//
|
||||
/**
|
||||
* Gets the webApplicationFactory value.
|
||||
* @return The webApplicationFactory value.
|
||||
*/
|
||||
public IWebApplicationFactory getWebApplicationFactory() {
|
||||
return (IWebApplicationFactory) getAttributeValue(WEB_APPLICATION_FACTORY);
|
||||
}//getWebApplicationFactory()//
|
||||
/**
|
||||
* Sets the webApplicationFactory value.
|
||||
* @param webApplicationFactory The webApplicationFactory value.
|
||||
*/
|
||||
public void setWebApplicationFactory(IWebApplicationFactory webApplicationFactory) {
|
||||
setAttributeValue(WEB_APPLICATION_FACTORY, webApplicationFactory);
|
||||
}//setWebApplicationFactory()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.model.Model#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "WebappBundle (Name:" + getName() + ")";
|
||||
}//toString()//
|
||||
}//WebappMetadata//
|
||||
@@ -0,0 +1,243 @@
|
||||
package com.foundation.web.server.shared.model;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
import com.common.debug.DefaultLog;
|
||||
import com.common.io.StreamSupport;
|
||||
import com.common.util.StringSupport;
|
||||
import com.foundation.metadata.Attribute;
|
||||
import com.foundation.metadata.Event;
|
||||
|
||||
/**
|
||||
* Encapsulates a log for a single web application.
|
||||
* Logs are written to file, are accessable from file in blocks, and are fired as events for any active listeners.
|
||||
* The design minimizes memory usage primarily while secondarily maximizing performance and accessiblity.
|
||||
* Old logs from a previous run will be discarded by this system automatically.
|
||||
*/
|
||||
public class WebappLog extends AbstractModel implements IWebappLog {
|
||||
public static final DefaultLog _log = new DefaultLog();
|
||||
public static final Event NEW_ENTRY = registerEvent(WebappLog.class, "newEntry");
|
||||
|
||||
private static final int HEADER_SIZE = 16;
|
||||
private static final int INDEX_SIZE = 8;
|
||||
|
||||
/** Contains log entries in order of occurance. */
|
||||
private File logFile = null;
|
||||
private RandomAccessFile logRaf = null;
|
||||
private FileChannel logChannel = null;
|
||||
/** The index file contains the index of the last byte in the indexed entry. So the first long value points to the last byte of the first log entry in the log file. */
|
||||
private File indexFile = null;
|
||||
private RandomAccessFile indexRaf = null;
|
||||
private FileChannel indexChannel = null;
|
||||
/** The number of entries in the log file & index file. */
|
||||
private int entryCount = 0;
|
||||
/** The position in the log file of the last byte written. This should always initially be zero. */
|
||||
private long lastPosition = 0;
|
||||
/** The reusable buffer for writing the position indices to the index file. */
|
||||
private ByteBuffer positionBuffer = ByteBuffer.allocate(INDEX_SIZE);
|
||||
/** The reusable buffer for reading/writing the header for a log entry. [Timestamp (8); Type Code (4); Truncated Text Length (4)] */
|
||||
private ByteBuffer headerBuffer = ByteBuffer.allocate(HEADER_SIZE);
|
||||
/**
|
||||
* WebappLog constructor.
|
||||
*/
|
||||
public WebappLog() {
|
||||
}//WebappLog()//
|
||||
/**
|
||||
* WebappLog constructor.
|
||||
* @param logFileRoot The root path where log files are kept.
|
||||
* @param webappName The name of the webapp which will be used to name the log file.
|
||||
*/
|
||||
public WebappLog(File logFileRoot, String webappName) throws IOException {
|
||||
logFile = new File(logFileRoot, (webappName == null ? "WebServer" : webappName) + ".log");
|
||||
indexFile = new File(logFileRoot, (webappName == null ? "WebServer" : webappName) + ".ind");
|
||||
|
||||
if(logFile.exists()) {
|
||||
logFile.delete();
|
||||
}//if//
|
||||
|
||||
if(!logFile.getParentFile().exists()) {
|
||||
logFile.getParentFile().mkdirs();
|
||||
}//if//
|
||||
|
||||
if(indexFile.exists()) {
|
||||
indexFile.delete();
|
||||
}//if//
|
||||
|
||||
if(!indexFile.getParentFile().exists()) {
|
||||
indexFile.getParentFile().mkdirs();
|
||||
}//if//
|
||||
|
||||
logRaf = new RandomAccessFile(logFile, "rw");
|
||||
logChannel = logRaf.getChannel();
|
||||
indexRaf = new RandomAccessFile(indexFile, "rw");
|
||||
indexChannel = indexRaf.getChannel();
|
||||
}//WebappLog()//
|
||||
/**
|
||||
* Adds the webapp log entry to the file system and notifies listeners.
|
||||
* @param entry The entry to add.
|
||||
*/
|
||||
public synchronized void addEntry(WebappLogEntry entry) {
|
||||
_log.log(entry.getText(), null, entry.getType().intValue(), false);
|
||||
try {
|
||||
long startPosition = lastPosition;
|
||||
byte[] bytes = entry.getText().getBytes("UTF8");
|
||||
|
||||
//Setup the header buffer.//
|
||||
headerBuffer.clear();
|
||||
StreamSupport.writeLong(entry.getTimestamp().longValue(), headerBuffer, StreamSupport.NUMBER_MSF);
|
||||
StreamSupport.writeInt(entry.getType().intValue(), headerBuffer, StreamSupport.NUMBER_MSF);
|
||||
StreamSupport.writeInt(entry.getShortLength().intValue(), headerBuffer, StreamSupport.NUMBER_MSF);
|
||||
//System.out.println("Writing timestamp: " + entry.getTimestamp().longValue());
|
||||
//System.out.println("Writing type: " + entry.getType().intValue());
|
||||
//System.out.println("Writing short length: " + entry.getShortLength().intValue());
|
||||
headerBuffer.flip();
|
||||
//Determine the position of the last byte in the current log entry.//
|
||||
lastPosition += bytes.length + HEADER_SIZE;
|
||||
positionBuffer.clear();
|
||||
StreamSupport.writeLong(lastPosition, positionBuffer, StreamSupport.NUMBER_MSF);
|
||||
//System.out.println("Writing position: " + lastPosition);
|
||||
positionBuffer.flip();
|
||||
//Write the position of the last byte of content in the new log entry.//
|
||||
indexChannel.write(positionBuffer, entryCount << 3);
|
||||
//Write the log entry to the log file.//
|
||||
logChannel.position(startPosition);
|
||||
logChannel.write(headerBuffer);
|
||||
logChannel.write(ByteBuffer.wrap(bytes));
|
||||
//System.out.println("Writing content:\n" + new String(bytes, "UTF8"));
|
||||
//System.out.println("Channel Position:" + logChannel.position());
|
||||
//Track the number of log entries.//
|
||||
entryCount++;
|
||||
//Fire the new entry event.//
|
||||
getEventSupport().fireEvent(NEW_ENTRY, entry, false);
|
||||
|
||||
////Test
|
||||
//logChannel.position(0);
|
||||
//ByteBuffer b = ByteBuffer.allocate((int) logChannel.size());
|
||||
//logChannel.read(b);
|
||||
//System.out.println("Current File Contents: \n" + StreamSupport.getHexString(b.array()));
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}//catch//
|
||||
}//addEntry()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.web.model.IWebappLog#getEntryCount()
|
||||
*/
|
||||
public synchronized int getEntryCount() {
|
||||
return entryCount;
|
||||
}//getEntryCount()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.web.model.IWebappLog#getEntries(int, int)
|
||||
*/
|
||||
public synchronized WebappLogEntry[] getEntries(int index, int count) throws IOException {
|
||||
long offset = 0;
|
||||
ByteBuffer positions;
|
||||
long[] sizes = new long[count];
|
||||
long previousOffset = 0;
|
||||
ByteBuffer contentBuffer;
|
||||
long maxSize = 0;
|
||||
WebappLogEntry[] result;
|
||||
|
||||
if(index < 0 || index > entryCount) {
|
||||
throw new IllegalArgumentException("Invalid index.");
|
||||
}//if//
|
||||
|
||||
if(count < 1 || count + index > entryCount) {
|
||||
throw new IllegalArgumentException("Invalid count.");
|
||||
}//if//
|
||||
|
||||
//Setup the result container.//
|
||||
result = new WebappLogEntry[count];
|
||||
//Initialize the positions buffer.//
|
||||
positions = ByteBuffer.allocate((index == 0 ? count : count + 1) << 3);
|
||||
//Read the positions.//
|
||||
indexChannel.read(positions, index == 0 ? 0 : (index - 1) << 3);
|
||||
positions.flip();
|
||||
|
||||
//Calculate the offset of the first content byte to read within the log file.//
|
||||
if(index != 0) {
|
||||
offset = StreamSupport.readLong(positions, StreamSupport.NUMBER_MSF);
|
||||
}//if//
|
||||
|
||||
//Gather the array of entry sizes in the log file.//
|
||||
for(int sizeIndex = 0; sizeIndex < count; sizeIndex++) {
|
||||
//Get the position of the last byte of content for the index.//
|
||||
long nextOffset = StreamSupport.readLong(positions, StreamSupport.NUMBER_MSF);
|
||||
//System.out.println("Read position: " + nextOffset);
|
||||
|
||||
//If this is the first content read then use the offset, otherwise use the previous position.//
|
||||
if(sizeIndex == 0) {
|
||||
sizes[sizeIndex] = nextOffset - offset;
|
||||
}//if//
|
||||
else {
|
||||
sizes[sizeIndex] = nextOffset - previousOffset;
|
||||
}//else//
|
||||
|
||||
//Remember the largest message size for later.//
|
||||
maxSize = Math.max(sizes[sizeIndex], maxSize);
|
||||
//Retain the previous offset.//
|
||||
previousOffset = nextOffset;
|
||||
}//for//
|
||||
|
||||
//Set the starting read position.//
|
||||
logChannel.position(offset);
|
||||
contentBuffer = ByteBuffer.allocate((int) (maxSize - headerBuffer.capacity()));
|
||||
|
||||
//Read each log entry.//
|
||||
for(int entryIndex = 0; entryIndex < count; entryIndex++) {
|
||||
WebappLogEntry next = new WebappLogEntry();
|
||||
|
||||
//System.out.println("LogChannel Position: " + logChannel.position());
|
||||
//Read the header for the entry.//
|
||||
headerBuffer.clear();
|
||||
logChannel.read(headerBuffer);
|
||||
headerBuffer.flip();
|
||||
//System.out.println("Header Buffer Contents: " + StreamSupport.getHexString(headerBuffer.array()));
|
||||
//Read the content for the entry.//
|
||||
contentBuffer.clear();
|
||||
//System.out.println("LogChannel Position: " + logChannel.position());
|
||||
contentBuffer.limit((int) (sizes[entryIndex] - HEADER_SIZE));
|
||||
logChannel.read(contentBuffer);
|
||||
contentBuffer.flip();
|
||||
//System.out.println("Content Buffer Contents: " + StreamSupport.getHexString(contentBuffer.array(), 0, contentBuffer.limit()));
|
||||
//Initialize the entry.//
|
||||
next.setTimestamp(new Long(StreamSupport.readLong(headerBuffer, StreamSupport.NUMBER_MSF)));
|
||||
next.setType(new Integer(StreamSupport.readInt(headerBuffer, StreamSupport.NUMBER_MSF)));
|
||||
next.setShortLength(new Integer(StreamSupport.readInt(headerBuffer, StreamSupport.NUMBER_MSF)));
|
||||
//System.out.println("Read timestamp: " + next.getTimestamp().longValue());
|
||||
//System.out.println("Read type: " + next.getType().intValue());
|
||||
//System.out.println("Read short length: " + next.getShortLength().intValue());
|
||||
next.setText(new String(contentBuffer.array(), contentBuffer.position(), contentBuffer.remaining(), "UTF8"));
|
||||
//Save the result.//
|
||||
result[entryIndex] = next;
|
||||
}//for//
|
||||
|
||||
return result;
|
||||
}//getEntries()//
|
||||
/**
|
||||
* Closes the log and cleans up all resources.
|
||||
*/
|
||||
public synchronized void close() {
|
||||
if(logChannel != null) {
|
||||
try {logChannel.close();} catch(Throwable e) {}
|
||||
}//if//
|
||||
|
||||
if(logRaf != null) {
|
||||
try {logRaf.close();} catch(Throwable e) {}
|
||||
}//if//
|
||||
|
||||
if(indexChannel != null) {
|
||||
try {indexChannel.close();} catch(Throwable e) {}
|
||||
}//if//
|
||||
|
||||
if(indexRaf != null) {
|
||||
try {indexRaf.close();} catch(Throwable e) {}
|
||||
}//if//
|
||||
}//close()//
|
||||
}//WebappLog//
|
||||
@@ -0,0 +1,159 @@
|
||||
package com.foundation.web.server.shared.model;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.common.debug.ILog;
|
||||
import com.common.io.StreamSupport;
|
||||
import com.foundation.metadata.Attribute;
|
||||
|
||||
/**
|
||||
* Represents a single entry in a webapp log.
|
||||
*/
|
||||
public class WebappLogEntry extends AbstractModel {
|
||||
public static final int TYPE_ERROR = ILog.TYPE_ERROR;
|
||||
public static final int TYPE_WARNING = ILog.TYPE_WARNING;
|
||||
public static final int TYPE_INFORMATION = ILog.TYPE_INFORMATION;
|
||||
|
||||
public static final Attribute TIMESTAMP = registerAttribute(WebappLogEntry.class, "timestamp");
|
||||
public static final Attribute TYPE = registerAttribute(WebappLogEntry.class, "type");
|
||||
public static final Attribute SHORT_LENGTH = registerAttribute(WebappLogEntry.class, "shortLength");
|
||||
public static final Attribute TEXT = registerAttribute(WebappLogEntry.class, "text");
|
||||
/**
|
||||
* WebappLogEntry constructor.
|
||||
*/
|
||||
public WebappLogEntry() {
|
||||
}//WebappLogEntry()//
|
||||
/**
|
||||
* WebappLogEntry constructor.
|
||||
*/
|
||||
public WebappLogEntry(int type, String text, Throwable exception) {
|
||||
try {
|
||||
int shortLength = 0;
|
||||
String shortText = null;
|
||||
String fullText = null;
|
||||
long timestamp = System.currentTimeMillis();
|
||||
|
||||
//Write the log entry to a byte array.//
|
||||
if(exception != null) {
|
||||
StringWriter stringWriter = new StringWriter(1000);
|
||||
PrintWriter printWriter = new PrintWriter(stringWriter);
|
||||
|
||||
if(text != null) {
|
||||
printWriter.append(text);
|
||||
printWriter.append("\n");
|
||||
shortText = text;
|
||||
}//if//
|
||||
else {
|
||||
shortText = exception.getMessage();
|
||||
}//else//
|
||||
|
||||
exception.printStackTrace(printWriter);
|
||||
fullText = stringWriter.getBuffer().toString();
|
||||
}//if//
|
||||
else if(text != null) {
|
||||
fullText = text;
|
||||
shortText = text;
|
||||
}//else if//
|
||||
|
||||
//Ensure that the short text doesn't contain any line ends, if so then shorten to exclude them.//
|
||||
if(shortText != null) {
|
||||
int index1 = shortText.indexOf("\r\n");
|
||||
int index2 = shortText.indexOf('\n');
|
||||
|
||||
shortLength = Math.min(index1 == -1 ? shortText.length() : index1, index2 == -1 ? shortText.length() : index2);
|
||||
|
||||
if(shortLength == -1) {
|
||||
shortLength = shortText.length();
|
||||
}//if//
|
||||
}//if//
|
||||
|
||||
setTimestamp(new Long(timestamp));
|
||||
setType(new Integer(type));
|
||||
setShortLength(new Integer(shortLength));
|
||||
setText(fullText);
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}//catch//
|
||||
}//WebappLogEntry()//
|
||||
/**
|
||||
* Gets the short version of the full text.
|
||||
* @return The short text representing this entry.
|
||||
*/
|
||||
public String getShortText() {
|
||||
String result;
|
||||
|
||||
if(getShortLength() != null && getShortLength().intValue() < getText().length()) {
|
||||
result = getText().substring(0, getShortLength().intValue());
|
||||
}//if//
|
||||
else {
|
||||
result = getText();
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//getShortText()//
|
||||
/**
|
||||
* Gets the timestamp of the entry.
|
||||
* @return The entry timestamp.
|
||||
*/
|
||||
public Long getTimestamp() {
|
||||
return (Long) getAttributeValue(TIMESTAMP);
|
||||
}//getTimestamp()//
|
||||
/**
|
||||
* Sets the timestamp of the entry.
|
||||
* @param timestamp The entry timestamp.
|
||||
*/
|
||||
public void setTimestamp(Long timestamp) {
|
||||
setAttributeValue(TIMESTAMP, timestamp);
|
||||
}//setTimestamp()//
|
||||
/**
|
||||
* Gets the type code describing how the entry should be treated (generally whether it is an error, warning, or information).
|
||||
* @return The entry type code.
|
||||
*/
|
||||
public Integer getType() {
|
||||
return (Integer) getAttributeValue(TYPE);
|
||||
}//getType()//
|
||||
/**
|
||||
* Sets the type code describing how the entry should be treated (generally whether it is an error, warning, or information).
|
||||
* @param type The entry type code.
|
||||
*/
|
||||
public void setType(Integer type) {
|
||||
setAttributeValue(TYPE, type);
|
||||
}//setType()//
|
||||
/**
|
||||
* Gets the number of characters in the truncated version of the text.
|
||||
* @return The character count for the short version displayable in a list or otherwise space constrained environment.
|
||||
*/
|
||||
public Integer getShortLength() {
|
||||
return (Integer) getAttributeValue(SHORT_LENGTH);
|
||||
}//getShortLength()//
|
||||
/**
|
||||
* Sets the number of characters in the truncated version of the text.
|
||||
* @param shortLength The character count for the short version displayable in a list or otherwise space constrained environment.
|
||||
*/
|
||||
public void setShortLength(Integer shortLength) {
|
||||
setAttributeValue(SHORT_LENGTH, shortLength);
|
||||
}//setShortLength()//
|
||||
/**
|
||||
* Gets the actual text for the log entry.
|
||||
* @return The full log text.
|
||||
*/
|
||||
public String getText() {
|
||||
return (String) getAttributeValue(TEXT);
|
||||
}//getText()//
|
||||
/**
|
||||
* Sets the actual text for the log entry.
|
||||
* @param text The full log text.
|
||||
*/
|
||||
public void setText(String text) {
|
||||
setAttributeValue(TEXT, text);
|
||||
}//setText()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.model.Model#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "WebappLogEntry\n" + getText();
|
||||
}//toString()//
|
||||
}//WebappLogEntry//
|
||||
Reference in New Issue
Block a user