/*******************************************************************************
* Copyright 2009, 2010 Innovation Gate GmbH. All Rights Reserved.
*
* This file is part of the OpenWGA server platform.
*
* OpenWGA is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition, a special exception is granted by the copyright holders
* of OpenWGA called "OpenWGA plugin exception". You should have received
* a copy of this exception along with OpenWGA in file COPYING.
* If not, see <http://www.openwga.com/gpl-plugin-exception>.
*
* OpenWGA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenWGA in file COPYING.
* If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package de.innovationgate.wgpublisher;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.prefs.Preferences;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import javax.activation.DataHandler;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.management.ObjectName;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.PageContext;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.collections.map.LinkedMap;
import org.apache.commons.jxpath.CompiledExpression;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.collections.Buffer;
import org.apache.commons.collections.BufferUtils;
import org.apache.commons.collections.buffer.CircularFifoBuffer;
import org.apache.commons.vfs.FileSystemException;
import org.apache.log4j.Appender;
import org.apache.log4j.AsyncAppender;
import org.apache.log4j.DailyRollingFileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.lucene.analysis.Analyzer;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.quartz.SchedulerException;
import org.quartz.impl.DirectSchedulerFactory;
import org.quartz.simpl.RAMJobStore;
import org.quartz.simpl.SimpleThreadPool;
import org.quartz.spi.JobStore;
import org.quartz.spi.ThreadPool;
import biz.minaret.log4j.DatedFileAppender;
import de.innovationgate.monitoring.JmxManager;
import de.innovationgate.utils.Base64;
import de.innovationgate.utils.DESEncrypter;
import de.innovationgate.utils.DynamicClassLoadingChain;
import de.innovationgate.utils.FormattingException;
import de.innovationgate.utils.ObjectFormatter;
import de.innovationgate.utils.PatternListVerifier;
import de.innovationgate.utils.ReplaceProcessor;
import de.innovationgate.utils.TempFileInputStream;
import de.innovationgate.utils.WGUtils;
import de.innovationgate.utils.XStreamUtils;
import de.innovationgate.utils.cache.Cache;
import de.innovationgate.utils.cache.CacheException;
import de.innovationgate.utils.cache.CacheFactory;
import de.innovationgate.utils.net.IPv4Address;
import de.innovationgate.utils.net.IPv4Restriction;
import de.innovationgate.webgate.api.MimetypeDeterminationService;
import de.innovationgate.webgate.api.WGAPIException;
import de.innovationgate.webgate.api.WGBackendException;
import de.innovationgate.webgate.api.WGContent;
import de.innovationgate.webgate.api.WGDatabase;
import de.innovationgate.webgate.api.WGDatabaseConnectListener;
import de.innovationgate.webgate.api.WGDatabaseCore;
import de.innovationgate.webgate.api.WGDatabaseEvent;
import de.innovationgate.webgate.api.WGDesignProvider;
import de.innovationgate.webgate.api.WGException;
import de.innovationgate.webgate.api.WGFactory;
import de.innovationgate.webgate.api.WGHierarchicalDatabase;
import de.innovationgate.webgate.api.WGHierarchicalDatabaseCoreListener;
import de.innovationgate.webgate.api.WGIllegalArgumentException;
import de.innovationgate.webgate.api.WGIllegalStateException;
import de.innovationgate.webgate.api.WGLanguage;
import de.innovationgate.webgate.api.WGSystemException;
import de.innovationgate.webgate.api.WGUnavailableException;
import de.innovationgate.webgate.api.WGUserProfile;
import de.innovationgate.webgate.api.WGDatabase.ConnectAction;
import de.innovationgate.webgate.api.auth.AuthModuleFactory;
import de.innovationgate.webgate.api.auth.AuthenticationException;
import de.innovationgate.webgate.api.auth.AuthenticationModule;
import de.innovationgate.webgate.api.auth.AuthenticationSession;
import de.innovationgate.webgate.api.auth.CertAuthCapableAuthModule;
import de.innovationgate.webgate.api.auth.FileAuthenticationModule;
import de.innovationgate.webgate.api.auth.RequestBasedAuthenticationModule;
import de.innovationgate.webgate.api.modules.servers.DatabaseServerProperties;
import de.innovationgate.webgate.api.servers.WGDatabaseServer;
import de.innovationgate.webgate.api.utils.ContentStoreDumpManager;
import de.innovationgate.webgate.api.workflow.WGDefaultWorkflowEngine;
import de.innovationgate.wga.common.Constants;
import de.innovationgate.wga.common.LogLevel;
import de.innovationgate.wga.common.beans.csconfig.v1.CSConfig;
import de.innovationgate.wga.common.beans.csconfig.v1.ElementMapping;
import de.innovationgate.wga.common.beans.csconfig.v1.EncoderMapping;
import de.innovationgate.wga.common.beans.csconfig.v1.InvalidCSConfigVersionException;
import de.innovationgate.wga.common.beans.csconfig.v1.JobDefinition;
import de.innovationgate.wga.common.beans.csconfig.v1.MediaKey;
import de.innovationgate.wga.common.beans.csconfig.v1.PluginConfig;
import de.innovationgate.wga.common.beans.csconfig.v1.PluginID;
import de.innovationgate.wga.common.beans.csconfig.v1.PublisherOption;
import de.innovationgate.wga.common.beans.csconfig.v1.Version;
import de.innovationgate.wga.common.beans.csconfig.v2.Shortcut;
import de.innovationgate.wga.config.Administrator;
import de.innovationgate.wga.config.AuthenticationSource;
import de.innovationgate.wga.config.ConfigBean;
import de.innovationgate.wga.config.ConfigValidationException;
import de.innovationgate.wga.config.ContentDatabase;
import de.innovationgate.wga.config.ContentStore;
import de.innovationgate.wga.config.Database;
import de.innovationgate.wga.config.DatabaseServer;
import de.innovationgate.wga.config.DesignConfiguration;
import de.innovationgate.wga.config.DesignReference;
import de.innovationgate.wga.config.Domain;
import de.innovationgate.wga.config.FieldMapping;
import de.innovationgate.wga.config.FilterMapping;
import de.innovationgate.wga.config.MigrationMessage;
import de.innovationgate.wga.config.MigrationResult;
import de.innovationgate.wga.config.PersonalisationConfiguration;
import de.innovationgate.wga.config.PersonalisationDatabase;
import de.innovationgate.wga.config.Share;
import de.innovationgate.wga.config.WGAConfiguration;
import de.innovationgate.wga.config.WGAConfigurationMigrator;
import de.innovationgate.wga.model.BrowsingSecurity;
import de.innovationgate.wga.model.ValidationError;
import de.innovationgate.wga.modules.ModuleDefinition;
import de.innovationgate.wga.modules.ModuleDependencyException;
import de.innovationgate.wga.modules.ModuleInstantiationException;
import de.innovationgate.wga.modules.ModuleRegistry;
import de.innovationgate.wga.modules.ModuleType;
import de.innovationgate.wga.modules.options.OptionConversionException;
import de.innovationgate.wga.modules.options.OptionDefinition;
import de.innovationgate.wga.modules.options.OptionReader;
import de.innovationgate.wga.modules.options.PasswordOptionEncoder;
import de.innovationgate.wga.modules.properties.DesignSourceProperties;
import de.innovationgate.wga.modules.types.AuthenticationSourceModuleType;
import de.innovationgate.wga.modules.types.ContentDatabaseModuleType;
import de.innovationgate.wga.modules.types.ContentDatabasePublisherOptionsModuleType;
import de.innovationgate.wga.modules.types.ContentStoreModuleType;
import de.innovationgate.wga.modules.types.ContentStorePublisherOptionsModuleType;
import de.innovationgate.wga.modules.types.DatabaseServerModuleType;
import de.innovationgate.wga.modules.types.DesignSourceModuleType;
import de.innovationgate.wga.modules.types.FilterConfigModuleType;
import de.innovationgate.wga.modules.types.HTMLHeadInclusionModuleType;
import de.innovationgate.wga.modules.types.LanguageBehaviourModuleType;
import de.innovationgate.wga.modules.types.PasswordEncodingType;
import de.innovationgate.wga.modules.types.PersonalisationDatabaseModuleType;
import de.innovationgate.wga.modules.types.SchedulerTaskModuleType;
import de.innovationgate.wga.modules.types.ShareModuleType;
import de.innovationgate.wga.modules.types.WGAServerOptionsModuleType;
import de.innovationgate.wga.modules.types.WebTMLElementModuleType;
import de.innovationgate.wga.modules.types.WebTMLEncoderModuleType;
import de.innovationgate.wga.modules.types.WorkflowEngineModuleType;
import de.innovationgate.wgpublisher.SystemContainerManager.ContainerInfo;
import de.innovationgate.wgpublisher.auth.BruteForceLoginBlocker;
import de.innovationgate.wgpublisher.auth.CSAuthModule;
import de.innovationgate.wgpublisher.auth.DelegatingAuthModule;
import de.innovationgate.wgpublisher.auth.DomainRedirectionAuthModule;
import de.innovationgate.wgpublisher.auth.WGAAuthModuleFactory;
import de.innovationgate.wgpublisher.cache.FileCache;
import de.innovationgate.wgpublisher.cache.WebTMLCache;
import de.innovationgate.wgpublisher.design.WGADesignManager;
import de.innovationgate.wgpublisher.design.db.DBDesignProvider;
import de.innovationgate.wgpublisher.design.fs.FileSystemDesignProvider;
import de.innovationgate.wgpublisher.design.sync.DesignFileValidator;
import de.innovationgate.wgpublisher.events.EventManager;
import de.innovationgate.wgpublisher.expressions.ExpressionEngineFactory;
import de.innovationgate.wgpublisher.expressions.tmlscript.IsolatedJARLoader;
import de.innovationgate.wgpublisher.expressions.tmlscript.TMLScriptGlobal;
import de.innovationgate.wgpublisher.hdb.HDBModel;
import de.innovationgate.wgpublisher.labels.WGAResourceBundleManager;
import de.innovationgate.wgpublisher.lang.DynamicLanguageBehaviour;
import de.innovationgate.wgpublisher.lang.LanguageBehaviour;
import de.innovationgate.wgpublisher.lang.OnlyDefaultLanguageBehaviour;
import de.innovationgate.wgpublisher.lang.StaticLanguageBehaviour;
import de.innovationgate.wgpublisher.log.WGALoggerWrapper;
import de.innovationgate.wgpublisher.logserver.LogServer;
import de.innovationgate.wgpublisher.lucene.LuceneManager;
import de.innovationgate.wgpublisher.lucene.analysis.FileHandler;
import de.innovationgate.wgpublisher.lucene.analysis.StandardAnalyzer;
import de.innovationgate.wgpublisher.modules.poptions.ContentDatabasePublisherOptionsCollector;
import de.innovationgate.wgpublisher.modules.poptions.ContentStorePublisherOptionsCollector;
import de.innovationgate.wgpublisher.monitoring.WGAInformation;
import de.innovationgate.wgpublisher.plugins.InvalidPluginException;
import de.innovationgate.wgpublisher.plugins.PluginException;
import de.innovationgate.wgpublisher.plugins.WGAPlugin;
import de.innovationgate.wgpublisher.plugins.WGAPluginSet;
import de.innovationgate.wgpublisher.scheduler.ConfigurationException;
import de.innovationgate.wgpublisher.scheduler.JavaTask;
import de.innovationgate.wgpublisher.scheduler.Job;
import de.innovationgate.wgpublisher.scheduler.JobFailedException;
import de.innovationgate.wgpublisher.scheduler.JobSchedule;
import de.innovationgate.wgpublisher.scheduler.Scheduler;
import de.innovationgate.wgpublisher.scheduler.ScriptTask;
import de.innovationgate.wgpublisher.scheduler.Task;
import de.innovationgate.wgpublisher.shares.ShareDefinition;
import de.innovationgate.wgpublisher.shares.ShareInitException;
import de.innovationgate.wgpublisher.shares.ShareProperties;
import de.innovationgate.wgpublisher.url.DefaultURLBuilder;
import de.innovationgate.wgpublisher.url.TitlePathManager;
import de.innovationgate.wgpublisher.url.WGAURLBuilder;
import de.innovationgate.wgpublisher.webtml.utils.CRLFEncoder;
import de.innovationgate.wgpublisher.webtml.utils.EncodingFormatter;
import de.innovationgate.wgpublisher.webtml.utils.HTMLHeadInclusion;
import de.innovationgate.wgpublisher.webtml.utils.JavaScriptEncodingFormatter;
import de.innovationgate.wgpublisher.webtml.utils.PlainTextFormatter;
import de.innovationgate.wgpublisher.webtml.utils.TMLContext;
import de.innovationgate.wgpublisher.webtml.utils.TMLContextAwareFormatter;
import de.innovationgate.wgpublisher.webtml.utils.TMLException;
import de.innovationgate.wgpublisher.webtml.utils.TMLScriptHDBListenerFactory;
import de.innovationgate.wgpublisher.webtml.utils.URLEncodingFormatter;
import de.innovationgate.wgpublisher.webtml.utils.UniqueNamePartFormatter;
/**
* Base class of the WGA runtime, containing any configuration, maintaing access
* to any data source. Know what you are doing when you use this class!
*/
public class WGACore implements ServletContextListener, WGDatabaseConnectListener {
public static final String EXTERNAL_PERSDBS_FOLDER = "#persdbs";
/**
* A reader for WGA configuration options, that always takes the current WGA configuration and caches once read option values
*/
public class WGAConfigurationOptionReader {
private CompiledExpression _jxPath;
private Class<? extends ModuleType> _typeClass;
private Class<?> _implClass;
protected WGAConfigurationOptionReader(String xpath, Class<? extends ModuleType> typeClass, Class<?> implClass) {
_jxPath = JXPathContext.compile(xpath);
_typeClass = typeClass;
_implClass = implClass;
Object target = _jxPath.getValue(JXPathContext.newContext(getWgaConfiguration()));
if (!(target instanceof Map)) {
throw new IllegalArgumentException("Xpath " + xpath + " does not point to an options map");
}
}
public Object readOptionValueOrDefault(String optionName) {
Map<String,String> options = (Map<String,String>) _jxPath.getValue(JXPathContext.newContext(getWgaConfiguration()));
ModuleDefinition modDef = getModuleRegistry().getModuleDefinition(_typeClass, _implClass);
if (modDef == null) {
getLog().error("Cannot read module definition " + _typeClass.getName() + "/" + _implClass.getName());
return null;
}
try {
return getWgaConfiguration().getCachingOptionReader().readOptionValueOrDefault(options, optionName, modDef);
}
catch (OptionConversionException e) {
getLog().error("Exception reading server option '" + optionName + "'. Falling back to default", e);
OptionDefinition optDef = modDef.getOptionDefinitions().get(optionName);
if (optDef != null) {
try {
return OptionReader.unconvertOptionValue(optDef, optDef.getDefaultValue());
}
catch (OptionConversionException e1) {
getLog().error("Exception unconverting default value of server option '" + optionName + "'. Falling back to null", e);
}
}
return null;
}
}
}
public WGAConfigurationOptionReader getConfigOptionReader(String xpath, Class<? extends ModuleType> typeClass, Class<?> implClass) {
return new WGAConfigurationOptionReader(xpath, typeClass, implClass);
}
public class WGAMimetypeDeterminationService implements MimetypeDeterminationService {
public String determineByFilename(String fileName) {
return getServletContext().getMimeType(fileName);
}
}
public class VariableReplaceProcessor implements ReplaceProcessor {
public int replace(String text, int from, int to, Writer out) throws IOException {
// Isolate the variable
int varEnd = text.indexOf("}", from);
if (varEnd == -1) {
out.write(text.substring(from, to + 1));
return to + 1;
}
// Get the variable name
String varName = text.substring(from + 2, varEnd).trim();
// Perform replacements
if (varName.equals("wga.cfgdir")) {
out.write(getConfigFilePath());
}
else if (varName.equals("wga.datadir")) {
out.write(getWgaDataDir().getAbsolutePath());
}
else if (varName.equals("wga.devpluginsdir")) {
String devPluginsPath = getDeveloperPluginsPath();
if (devPluginsPath != null) {
out.write(devPluginsPath);
}
else {
out.write(getConfigFilePath());
}
}
else if (varName.equals("wga.defaultpluginsdir")) {
out.write( getServletContext().getRealPath("/WEB-INF/default-plugins"));
}
else if (varName.startsWith("sys.")) {
out.write(System.getProperty(varName.substring(5)));
}
else if (varName.startsWith("env.")) {
out.write(System.getenv(varName.substring(5)));
}
return varEnd + 1;
}
}
public final VariableReplaceProcessor _replaceProcessorInstance = new VariableReplaceProcessor();
/**
* Domain name used for administrative logins
*/
public static final String DOMAIN_ADMINLOGINS = "$adminlogins";
public static final String ENCODER_CRLF = "crlf";
public static final String ENCODER_RTFSYSTEM = "rtfsystem";
public static final String ENCODER_RTF = "rtf";
public static final String ENCODER_PLAINTEXT = "plaintext";
private static final String ENCODER_XML = "xml";
public static final String ENCODER_HTML = "html";
public static final String ENCODER_URL = "url";
public static final String ENCODER_JAVASCRIPT = "javascript";
public static final String ENCODER_NAMEPART = "np";
public static final String SYSPROPERTY_UNITTEST = "de.innovationgate.wga.unittest";
public static final String SYSPROPERTY_UNITTEST_LOGDIR = "de.innovationgate.wga.unittest.logdir";
public static final String DBATTRIB_DEFAULTPORT_BASE = "DefaultPort";
public static final String DBATTRIB_DEFAULTPORT_HTTP = "DefaultPortHTTP";
public static final String DBATTRIB_DEFAULTPORT_HTTPS = "DefaultPortHTTPS";
public static final PatternLayout LAYOUT_APPLOG = new PatternLayout("%d{dd.MM.yyyy HH:mm:ss} %p %m\n");
public static final String SYSPROPERTY_DEFAULT_PLUGINS = "de.innovationgate.wga.defaultplugins";
public static final String SYSPROPERTY_DEVELOPER_PLUGINS = "de.innovationgate.wga.devplugins";
public static final String SYSPROPERTY_LOGPATH = "de.innovationgate.wga.logpath";
/*
* Server options
*/
public static final String SERVEROPTION_SERVER_SCALINGTHRESHOLD = "Server.ScalingThreshold";
public static final String DBATTRIB_DIRECTACCESSDEFAULT = "DirectAccessDefault";
/**
* Publisher option defining the encoding of design resources - determines
* the encoding in which file base resources are read from filesystem -
* determines the source encoding for textual files within file containers
*/
public static final String DBATTRIB_DESIGN_ENCODING = "DesignEncoding";
/**
* Publisher option for redirecting URLs to this DB to a different protocol
*/
public static final String DBATTRIB_REDIRECTPROTOCOL = "RedirectProtocol";
/**
* Publisher option for redirecting URLs to this DB to a different host
*/
public static final String DBATTRIB_REDIRECTHOST = "RedirectHost";
/**
* Publisher option for redirecting URLs to this DB to a different port
*/
public static final String DBATTRIB_REDIRECTPORT = "RedirectPort";
//public static final String DBATTRIB_ISHDB = "isHDB";
//public static final String DBATTRIB_HDBINIT = "HDBInit";
public static final String DBATTRIB_HDB_USE_VERSIONING = WGHierarchicalDatabase.DBATTRIB_HDB_USE_VERSIONING;
public static final String SYSTEMLABEL_BASE_PATH = "de.innovationgate.wgpublisher.labels.";
public class DevPluginsMonitoringTask extends TimerTask {
private File _dir;
private long _lastChanged;
public DevPluginsMonitoringTask(File dir) {
_dir = dir;
_lastChanged = getLatestChange();
}
private long getLatestChange() {
long latestChange = Long.MIN_VALUE;
File[] files = _dir.listFiles();
for (File f : files) {
long fileLastMod = f.lastModified();
latestChange = (fileLastMod > latestChange ? fileLastMod : latestChange);
if (f.isDirectory()) {
File[] childFiles = f.listFiles();
for (File f2 : childFiles) {
long fileLastMod2 = f2.lastModified();
latestChange = (fileLastMod2 > latestChange ? fileLastMod2 : latestChange);
}
}
}
return latestChange;
}
@Override
public void run() {
try {
Thread.currentThread().setName("WGA Developer Plugins Monitoring Task");
synchronized (WGACore.this) {
boolean anythingRemoved = uninstallRemovedDefaultPlugins();
long newLastChanged = getLatestChange();
if (anythingRemoved || newLastChanged > _lastChanged) {
_lastChanged = newLastChanged;
updatePlugins();
}
}
}
catch (Throwable e) {
getLog().error("Exception executing developer plugins monitoring task", e);
}
}
}
public class ValidateDefaultLanguageAction implements ConnectAction {
public void run(WGDatabase db) throws Exception {
// Look if it is defined
WGLanguage defaultLanguage = db.getLanguage(db.getDefaultLanguage());
if (defaultLanguage == null || defaultLanguage.isDummy()) {
if (db.getLanguages().size() > 0) {
//WGACore.this.log.warn("The default language '" + db.getDefaultLanguage() + "' is not defined in database " + db.getDbReference() + ". As other language definitions exist this may be misconfigured.");
}
}
// Is there some root content in the default language? If so, we are satisfied.
if (defaultLanguage != null) {
WGContent content = db.getFirstReleasedContent(defaultLanguage.getName(), true);
if (content != null) {
return;
}
}
// No root content in default language? This may still be ok if there is no content at all. We try this with all languages.
WGContent content = null;
for (WGLanguage lang : db.getLanguages().values()) {
content = db.getFirstReleasedContent(lang.getName(), true);
if (content != null) {
break;
}
}
if (content == null) {
return;
}
// It seems there is content, but the currently selected default language is not available in any root doc.
// Now we ask the db to determine a new default language
db.determineDefaultLanguage();
WGACore.this.log.info("Default language of database " + db.getDbReference() + " changed to '" + db.getDefaultLanguage() + "'");
}
}
public final class ApplogPage {
private boolean pageExisting = false;
private boolean endReached = false;
private int endIndex = -1;
private List<ApplogMessage> _messages = null;
public ApplogPage(boolean pageReached, boolean endReached, int endIndex, List<ApplogMessage> messages) {
super();
this.pageExisting = pageReached;
this.endIndex = endIndex;
this.endReached = endReached;
_messages = messages;
}
public ApplogPage(boolean pageReached, boolean endReached, int endIndex) {
this(pageReached, endReached, endIndex, null);
}
public boolean isPageExisting() {
return pageExisting;
}
public int getEndIndex() {
return endIndex;
}
public boolean isEndReached() {
return endReached;
}
public List<ApplogMessage> getMessages() {
return _messages;
}
}
public static final class ApplogMessage {
public static final DecimalFormat LINENUMBER_FORMAT = new DecimalFormat("000000");
public static final Pattern MESSAGE_PATTERN = Pattern.compile("(\\d+.\\d+.\\d+ \\d+:\\d+:\\d+) (\\w+) (.+)");
public static final DateFormat MESSAGE_DATEFORMAT = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
private Date _time;
private LogLevel _level;
private String _mainMessage;
private StringBuffer _details = null;
private int _line;
public static ApplogMessage parseLine(String line, int lineNumber) {
Matcher messageMatcher = ApplogMessage.MESSAGE_PATTERN.matcher(line);
if (messageMatcher.matches()) {
return new ApplogMessage(messageMatcher, lineNumber);
}
else {
return null;
}
}
public ApplogMessage(Date time, LogLevel level, String mainMessage, int line) {
super();
_time = time;
_level = level;
_mainMessage = mainMessage;
_line = line;
}
public ApplogMessage(Matcher messageMatcher, int line) {
String dateStr = messageMatcher.group(1);
try {
_time = MESSAGE_DATEFORMAT.parse(dateStr);
}
catch (ParseException e) {
// Shouldn't happen. If it does we display bogus date
_time = new Date(Long.MIN_VALUE);
}
String logLevelStr = messageMatcher.group(2);
_level = LogLevel.getLevel(logLevelStr);
_mainMessage = messageMatcher.group(3);
_line = line;
}
public void addDetailsLine(String line) {
if (_details == null) {
_details = new StringBuffer();
}
_details.append(line).append("\n");
}
public Date getTime() {
return _time;
}
public LogLevel getLevel() {
return _level;
}
public String getMainMessage() {
return _mainMessage;
}
public String getDetails() {
if (_details != null) {
return _details.toString();
}
else {
return null;
}
}
public int getLine() {
return _line;
}
@Override
public String toString() {
StringBuffer str = new StringBuffer();
str.append(LINENUMBER_FORMAT.format(_line));
str.append(" ");
str.append(MESSAGE_DATEFORMAT.format(_time));
str.append(" ");
str.append(_level.toString());
str.append(" ");
str.append(_mainMessage);
String details = getDetails();
if (details != null) {
str.append("\n").append(details);
}
return str.toString();
}
}
/**
* Performs cleanup operations
*/
private final class CleanupTask extends TimerTask {
public void run() {
try {
Thread.currentThread().setName("WGA Core Cleanup Task");
// Cleanup transient scheduler jobs
getScheduler().clearTransientJobs();
}
catch (Throwable e) {
getLog().error("Exception running cleanup task", e);
}
}
}
public class UserAgentVerifier extends PatternListVerifier {
public UserAgentVerifier(PersonalisationConfiguration config, WGACore core) {
Iterator<String> agentExclusions = config.getPersonalisationAgentExclusions().iterator();
while (agentExclusions.hasNext()) {
String patternStr = agentExclusions.next();
try {
addPattern(patternStr);
}
catch (PatternSyntaxException e) {
core.getLog().error("Cannot parse user agent exclusion as regular expression: " + patternStr);
}
}
}
public boolean isValidUserAgent(String userAgent) {
// We accept no empty user agent, as it cannot be verified
if (userAgent == null) {
return false;
}
return (verify(userAgent) == null);
}
}
public class DomainConfiguration {
public static final int LOGINMODE_MASTER = 1;
public static final int LOGINMODE_USER = 2;
private Domain _config;
private AuthenticationModule _authModule;
/**
* @return Returns the name.
*/
public String getName() {
return _config.getName();
}
public DomainConfiguration(String name) {
_config = new Domain(name);
_config.setName(name);
}
public DomainConfiguration(Domain config) {
_config = config;
}
protected void init() {
if (_config != null) {
// Authentication
try {
AuthModuleFactory authFactory = WGFactory.getAuthModuleFactory();
AuthenticationSource authSource = _config.getAuthenticationSource();
if (authSource != null) {
_authModule = authFactory.getAuthModule(authSource.getImplClassName(), authSource.getOptions(), null);
}
}
catch (de.innovationgate.webgate.api.auth.ConfigurationException e) {
getLog().error("Authentication module of domain '" + getName() + "' is misconfigured and inactive", e);
}
}
}
/**
* @return Returns the authModule.
*/
public AuthenticationModule getAuthModule() {
return _authModule;
}
public AuthenticationSource getAuthenticationSource() {
if (_config != null) {
return _config.getAuthenticationSource();
} else {
return null;
}
}
public String getDefaultManager() {
return _config.getDefaultManager();
}
public int getMaximumLoginAttempts() {
return _config.getMaximumLoginAttempts();
}
public PersonalisationDatabase getPersonalisation() {
if (_config != null) {
return _config.getPersonalisation();
} else {
return null;
}
}
public int getLoginMode() {
return LOGINMODE_USER;
}
@Override
public String toString() {
if (_config != null) {
return _config.toString();
} else {
return super.toString();
}
}
public void destroy() {
if (_authModule != null) {
_authModule.destroy();
_authModule = null;
}
}
public String getUID() {
return _config.getUid();
}
}
public class ResourceConfiguration {
private String _faviconPath = null;
private String _defaultDatabase = null;
private int _staticExpiration = 10;
public ResourceConfiguration(Element defaultdb) {
setDefaultDatabase(defaultdb.attributeValue("key", null));
setFaviconPath(defaultdb.attributeValue("favicon", ""));
try {
setStaticExpiration(Integer.parseInt(defaultdb.attributeValue("staticexpiration", "10000")));
}
catch (NumberFormatException e1) {
getLog().error("Unable to parse Cache Expiration for static resources: " + defaultdb.attributeValue("staticexpiration", "10000"));
}
String dataCacheStr = defaultdb.attributeValue("datacache", "10000");
try {
int dataCache = Integer.parseInt(dataCacheStr);
if (dataCache != WGFactory.getInstance().getCacheCapacity()) {
getLog().info("WGAPI Data Cache Capacity is set to " + dataCache + " entries" + (WGFactory.getInstance().isCacheInitialized() ? " (ineffective until a data cache reset)" : ""));
WGFactory.getInstance().setCacheCapacity(dataCache);
}
}
catch (NumberFormatException e) {
getLog().error("Unable to parse WGAPI Data Cache Size as number: " + dataCacheStr);
}
}
public String getFaviconPath() {
return _faviconPath;
}
public void setFaviconPath(String faviconPath) {
if (faviconPath != null && faviconPath.trim().equals("")) {
faviconPath = null;
}
_faviconPath = faviconPath;
}
public String getDefaultDatabase() {
return _defaultDatabase;
}
public void setDefaultDatabase(String defaultDatabase) {
if (defaultDatabase != null && defaultDatabase.trim().equals("")) {
defaultDatabase = null;
}
_defaultDatabase = defaultDatabase;
}
public int getStaticExpiration() {
return _staticExpiration;
}
public void setStaticExpiration(int staticExpiration) {
_staticExpiration = staticExpiration;
}
}
public static final String ATTRIB_TMLDEBUG_TRACE_RESULTS = "tmlDebugTraceResults";
public static final String ATTRIB_CURRENTTML = "currenttml";
public static final String ATTRIB_AJAXINFO = "ajaxInfo";
private Scheduler _scheduler;
private BruteForceLoginBlocker bruteForceLoginBlocker = new BruteForceLoginBlocker(this);
private List syncMappings;
public static final String ATTRIB_TMLDEBUG_DOCUMENTS = "tmlDebugDocuments";
public static final String ATTRIB_TMLDEBUG = "tmlDebug";
public static final String ATTRIB_TMLDEBUG_DISABLE_TMLSCRIPT_OPTIMIZATION = "tmlDebugDisableTMLScriptOptimization";
public static final String ATTRIB_REQUESTTYPE = "RequestType";
public static final String ATTRIB_INCLUDELEVEL = "$IncludeLevel";
public static final String ATTRIB_EDITDOCUMENT = "editDocument";
public static final String DBSESSIONCONTEXT_REQUEST = "Request";
public static final String WGAMANAGER_URL = "wgamanager-4.0.jnlp";
public static final String LANGUAGEBEHAVIOUR_DEFAULT = "default";
public static final String LANGUAGEBEHAVIOUR_MAINCONTENT = "maincontent";
public static final String LANGUAGEBEHAVIOUR_BROWSER = "browser";
private static DynamicClassLoadingChain libraryClassLoadingChain;
private EventManager eventManager;
public static final String SESSION_COOKIESET = "CookieSet:";
public static final String DBATTRIB_SESSIONCOOKIE = "SessionCookie";
public static final String pubKey = "MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAMfEHZxC9JGRuMSI9fuKewoha0wsywr6Yi/F6k+YERZKD8GIPdzpWqcD8kQ0FZqxaI7T+1xH0oRbnr1aVsyZSfRICuhWUcoJrThsuuYBFmjMtl8XDW9saa0VDQirxpH5ee3JqCHJurp6ik0XtqI25NBVLiJZQ1aJt6Znt4FPEosw=";
private static final String SYSPROP_SKIP_LOCAL_ADMIN_LOGINS = "de.innovationgate.wga.skipLocalAdminLogins";
private static final String SYSPROP_WARNINGS_ON_SERVER_CONSOLE = "de.innovationgate.wga.outputWarningsOnConsole";
public class LicenseBindingKey implements Comparable {
private String _domain;
private String _name;
private String _type;
public LicenseBindingKey(String domain, String name, String type) {
_domain = domain.toLowerCase();
_name = name.toLowerCase();
_type = type;
}
public LicenseBindingKey(String complete) {
List elements = WGUtils.deserializeCollection(complete, "//");
_domain = (String) elements.get(0);
_name = (String) elements.get(1);
_type = (String) elements.get(2);
}
/*
* (Kein Javadoc)
*
* @see java.lang.Object#toString()
*/
public String toString() {
return _domain + "//" + _name + "//" + _type;
}
public String getDomain() {
return _domain;
}
public String getName() {
return _name;
}
public String getType() {
return _type;
}
/*
* (Kein Javadoc)
*
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
public int compareTo(Object o) {
return toString().compareTo(o.toString());
}
/*
* (Kein Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
return toString().equals(obj.toString());
}
/*
* (Kein Javadoc)
*
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return toString().hashCode();
}
}
/**
* checks if a login-retry is allowed - user can be redirected to login page
*
* @param db
* @param session
* @return
*/
public boolean allowLoginRetry(WGDatabase db, HttpSession session) {
boolean dbCertAuth = db.certAuthEnabled();
boolean domCertAuth = certAuthEnabledForDomain((String) db.getAttribute(WGACore.DBATTRIB_DOMAIN));
if (!dbCertAuth && domCertAuth) {
// we have a configuration conflict
log.warn("The domain '" + db.getAttribute(WGACore.DBATTRIB_DOMAIN) + "' is enabled for certificate authentication, but db '" + db.getDbReference()
+ "' is not configured to support certificates. All dbs in a domain must support the same user credentials.");
}
if (dbCertAuth || domCertAuth) {
// on certificate authentication a login retry makes no sense
// user should not be redirected to login page
return false;
}
else {
DBLoginInfo loginInfo = this.getSessionLogins(session).get(db.getAttribute(WGACore.DBATTRIB_DOMAIN));
return (loginInfo == null);
}
}
public String getDeveloperPluginsPath() {
String customDefaultPlugins = System.getProperty(SYSPROPERTY_DEVELOPER_PLUGINS);
if (customDefaultPlugins != null) {
File pluginsFolder = getWGAFile(customDefaultPlugins);
return pluginsFolder.getAbsolutePath();
}
else {
return null;
}
}
public boolean isAuthor(WGDatabase db, String ip, String type) {
if (db == null) {
return false;
}
if (!db.isSessionOpen()) {
return false;
}
// Check db access rights
if (db.getSessionContext().getAccessLevel() < WGDatabase.ACCESSLEVEL_AUTHOR) {
return false;
}
return true;
}
public boolean isAdminLogin(String name, String password) {
return isAdminLogin(name, password, null);
}
public boolean isAdminLogin(String name, String password, HttpServletRequest request) {
// check if we should allow passwordless admin login from localhost
if (request != null && isLocalRequest(request) && Boolean.parseBoolean(System.getProperty(SYSPROP_SKIP_LOCAL_ADMIN_LOGINS, "false"))) {
return true;
}
if (name == null || password == null) {
return false;
}
Administrator admin = (Administrator) _wgaConfiguration.getAdministrator(name);
if (admin == null) {
return false;
}
boolean loggedIn = getBruteForceLoginBlocker().login(admin, password);
if (request != null) {
if (!loggedIn) {
log.warn("Failed admin login attempt for account '" + name + "' from '" + request.getRemoteAddr() + "'.");
}
}
return loggedIn;
}
public boolean doAdminLogin(String name, String password, HttpServletRequest request) {
if (isAdminLogin(name, password, request)) {
request.getSession().setAttribute(WGACore.SESSION_ADMINNAME, name);
request.getSession().setAttribute(WGACore.SESSION_ADMINPASSWORD, password);
return true;
} else {
request.getSession().removeAttribute(WGACore.SESSION_ADMINNAME);
request.getSession().removeAttribute(WGACore.SESSION_ADMINPASSWORD);
return false;
}
}
public String getElementClassForName(String name) throws TMLException {
String className = this.systemElements.get(name.toLowerCase());
if (className == null) {
className = this.customElements.get(name.toLowerCase());
}
if (className == null) {
ModuleDefinition modDef = getModuleRegistry().getModuleDefinitionByKey(WebTMLElementModuleType.class, name.toLowerCase());
if (modDef != null) {
try {
modDef.testDependencies();
}
catch (ModuleDependencyException e) {
throw new TMLException("WebTML element '" + name + "' not available bc. of missing dependency: " + e.getMessage(), true);
}
className = modDef.getImplementationClass().getName();
}
}
return className;
}
public String getConfigFilePath() {
try {
return this.getConfigFile().getPath();
}
catch (Exception e) {
this.log.error("Error retrieving config file path", e);
return "(Error retrieving config file path)";
}
}
public ApplogPage writeApplogContent(int offset, int size, Writer out, LogLevel loglevel, boolean lineNumbers) {
DecimalFormat lineNumberFormat = new DecimalFormat("000000");
Iterator logFiles = transientLogAppender.getActiveFiles().iterator();
if (offset < 1) {
return new ApplogPage(false, false, -1);
}
int totalLinesCount = 0;
boolean firstLine = true;
boolean pageReached = false;
boolean endReached = true;
filesloop:
while (logFiles.hasNext()) {
ApplogAppender.AppenderFile appenderFile = (ApplogAppender.AppenderFile) logFiles.next();
// If the line count of this logfile is known, and it is not the last one (which still might grow)
// it might be skipped when we need a line beyond it
if (logFiles.hasNext() && appenderFile.getLinesCount() != -1) {
if (totalLinesCount + appenderFile.getLinesCount() < offset) {
totalLinesCount += appenderFile.getLinesCount();
continue;
}
}
synchronized (appenderFile.getFile()) {
LineNumberReader reader = null;
try {
reader = new LineNumberReader(new FileReader(appenderFile.getFile()));
LogLevel level = LogLevel.LEVEL_INFO;
String line;
// Skip lines that are below the offset
while (offset > (totalLinesCount + 1)) {
line = reader.readLine();
if (line == null) {
appenderFile.setLinesCount(reader.getLineNumber());
continue filesloop;
}
totalLinesCount++;
level = LogLevel.isolateLogLevel(line, 20, level);
}
int toLine = offset + size - 1;
// Read lines that are in the targeted region
while (totalLinesCount < toLine) {
line = reader.readLine();
if (line == null) {
appenderFile.setLinesCount(reader.getLineNumber());
continue filesloop;
}
totalLinesCount++;
level = LogLevel.isolateLogLevel(line, 20, level);
// Filter level
if (level.isHigherOrEqual(loglevel)) {
pageReached = true;
// Add line break only if not on first line
if (firstLine) {
firstLine = false;
}
else {
out.write("\n");
}
if (lineNumbers) {
out.write(lineNumberFormat.format(totalLinesCount));
out.write(" ");
}
out.write(line);
}
else {
toLine++;
}
}
endReached = false;
}
catch (FileNotFoundException e) {
getLog().error("Error reading application log", e);
return new ApplogPage(false, false, totalLinesCount);
}
catch (IOException e) {
getLog().error("Error reading application log", e);
return new ApplogPage(false, false, totalLinesCount);
}
finally {
try {
if (reader != null) {
reader.close();
}
}
catch (IOException e) {
getLog().error("Error closing application log reader", e);
}
}
}
}
return new ApplogPage(pageReached, endReached, totalLinesCount);
}
public int getApplogLines() {
return getApplogContent(Integer.MAX_VALUE, 1, LogLevel.LEVEL_ALL).getEndIndex();
}
public ApplogPage getApplogContent(int offset, int size, LogLevel loglevel) {
DecimalFormat lineNumberFormat = new DecimalFormat("000000");
Iterator logFiles = transientLogAppender.getActiveFiles().iterator();
if (offset < 1) {
return new ApplogPage(false, false, -1);
}
int totalLinesCount = 0;
boolean firstLine = true;
boolean pageReached = false;
boolean endReached = true;
List<ApplogMessage> messages = new ArrayList<ApplogMessage>();
ApplogMessage currentMessage = null;
filesloop:
while (logFiles.hasNext()) {
endReached = false;
ApplogAppender.AppenderFile appenderFile = (ApplogAppender.AppenderFile) logFiles.next();
// If the line count of this logfile is known, and it is not the last one (which still might grow)
// it might be skipped when we need a line beyond it
if (logFiles.hasNext() && appenderFile.getLinesCount() != -1) {
if (totalLinesCount + appenderFile.getLinesCount() < offset) {
totalLinesCount += appenderFile.getLinesCount();
continue;
}
}
synchronized (appenderFile.getFile()) {
LineNumberReader reader = null;
try {
reader = new LineNumberReader(new FileReader(appenderFile.getFile()));
String line;
// Skip lines that are below the offset
while (offset > (totalLinesCount + 1)) {
line = reader.readLine();
if (line == null) {
appenderFile.setLinesCount(reader.getLineNumber());
endReached = true;
continue filesloop;
}
totalLinesCount++;
}
// Read lines that are in the targeted region
while (true) {
line = reader.readLine();
if (line == null) {
appenderFile.setLinesCount(reader.getLineNumber());
endReached = true;
continue filesloop;
}
totalLinesCount++;
ApplogMessage newMessage = ApplogMessage.parseLine(line, totalLinesCount);
if (newMessage != null) {
// Add previous message to list
if (currentMessage != null) {
if (currentMessage.getLevel().isHigherOrEqual(loglevel)) {
pageReached = true;
messages.add(currentMessage);
currentMessage = null;
// The message size is reached we go back one line and exit the loop
if (messages.size() == size) {
totalLinesCount--;
break filesloop;
}
}
}
currentMessage = newMessage;
}
else {
if (currentMessage != null) {
currentMessage.addDetailsLine(line);
}
// The offset does not start with a regular message. We ignore these lines
else {
continue;
}
}
}
}
catch (FileNotFoundException e) {
getLog().error("Error reading application log", e);
return new ApplogPage(false, false, totalLinesCount);
}
catch (IOException e) {
getLog().error("Error reading application log", e);
return new ApplogPage(false, false, totalLinesCount);
}
finally {
try {
if (reader != null) {
reader.close();
}
}
catch (IOException e) {
getLog().error("Error closing application log reader", e);
}
}
}
}
if (currentMessage != null && currentMessage.getLevel().isHigherOrEqual(loglevel)) {
messages.add(currentMessage);
}
return new ApplogPage(pageReached, endReached, totalLinesCount, messages);
}
public MediaKey getMediaKey(String key) {
MediaKey mediaKey = this.systemMediaKeys.get(key);
if (mediaKey == null) {
mediaKey = this.customMediaKeys.get(key);
}
return mediaKey;
}
public Set<String> getMediaKeys() {
Set<String> set = new HashSet<String>();
set.addAll(systemMediaKeys.keySet());
set.addAll(customMediaKeys.keySet());
return set;
}
public boolean isDeploymentKeyDefined(String layoutKey) {
return this.deployer.getLayoutMappings().containsKey(layoutKey);
}
public HashMap<Object, DBLoginInfo> getSessionLogins(javax.servlet.http.HttpSession session) {
HashMap<Object, DBLoginInfo> logins = (HashMap<Object, DBLoginInfo>) session.getAttribute(WGPDispatcher.SESSION_LOGINS);
if (logins == null) {
logins = new HashMap<Object, DBLoginInfo>();
session.setAttribute(WGPDispatcher.SESSION_LOGINS, logins);
}
return logins;
}
public WGDatabase openContentDB(String key, javax.servlet.http.HttpServletRequest request) throws WGException {
return openContentDB(key, request, false);
}
public WGDatabase openContentDB(String key, javax.servlet.http.HttpServletRequest request, boolean useMaster) throws WGException {
WGDatabase db = this.contentdbs.get(key);
if (db != null) {
return openContentDB(db, request, useMaster);
}
else {
return null;
}
}
public WGDatabase openContentDB(WGDatabase db, javax.servlet.http.HttpServletRequest request, boolean useMaster) throws WGException {
return openContentDB(db, request, useMaster, null);
}
public WGDatabase openContentDB(WGDatabase db, javax.servlet.http.HttpServletRequest request, boolean useMaster, WGDatabase hintDB) throws WGException {
// If already open, just return
if (db.isSessionOpen()) {
return db;
}
// If db is not ready throw an exception
if (!db.isReady()) {
throw new WGUnavailableException(db);
}
// Force master login
if (useMaster) {
db.openSession(null, null);
return prepareDB(db, request);
}
// check client access to this db
if (request != null && !this.isClientPermitted(db, request)) {
throw new ClientAccessException("Client '" + request.getRemoteAddr() + "' is not permitted to access db '" + db.getDbReference() + "'.");
}
// Check if a regular login is forced by some filter
Boolean forceRegular = (request != null ? (Boolean) request.getAttribute(ATTRIB_FORCEREGULARLOGIN) : null);
if (forceRegular == null) {
forceRegular = Boolean.FALSE;
}
// Certificate based login
if (!forceRegular.booleanValue() && db.certAuthEnabled()) {
return openContentDBCertAuth(db, request);
}
// Requestinfo based login
else if (!forceRegular.booleanValue() && db.getAuthenticationModule() != null && db.getAuthenticationModule() instanceof RequestBasedAuthenticationModule) {
return openContentDBRequestBased(db, request);
}
else {
// do standard login process
DomainConfiguration domainConfig = getDomainConfigForDatabase(db);
// If no session available, log in by hint or anonymous
HttpSession session = (request != null ? request.getSession() : null);
if (session == null) {
if (hintDB != null && hintDB.isSessionOpen()) {
DomainConfiguration hintDomain = getDomainConfigForDatabase(hintDB);
if (hintDomain.getLoginMode() == domainConfig.getLoginMode()) {
if (hintDB.getSessionContext().isMasterSession()) {
db.openSession();
}
else {
db.openSession(hintDB.getSessionContext().getUser(), hintDB.getSessionContext().getPassword());
}
if (db.isSessionOpen()) {
return prepareDB(db, request);
}
}
}
db.openSession(WGDatabase.ANONYMOUS_USER, null);
return prepareDB(db, request);
}
// Look if domain is defined
// If login mode MASTER, log in by master login
if (domainConfig.getLoginMode() == DomainConfiguration.LOGINMODE_MASTER) {
db.openSession(null, null);
return prepareDB(db, request);
}
// Try to login by (previously stored) domain-specific login
DBLoginInfo loginInfo = this.getSessionLogins(session).get(domainConfig.getName());
if (loginInfo != null) {
int accessLevel = db.openSession(loginInfo.getUserName(), loginInfo.getCredentials());
if (accessLevel > WGDatabase.ACCESSLEVEL_NOTLOGGEDIN) {
return prepareDB(db, request);
}
else {
if (domainConfig.getAuthModule() != null) {
getLog().warn(
"User '" + loginInfo.getUserName() + "' could not login to database '" + db.getAttribute(DBATTRIB_DBKEY)
+ "' although she/he could login to the domain authentication. Is the domain '" + db.getAttribute(DBATTRIB_DOMAIN) + "' misconfigured?");
}
else {
getLog().warn(
"User '" + loginInfo.getUserName() + "' could not login to database '" + db.getAttribute(DBATTRIB_DBKEY)
+ "' although another db in the same domain permitted it. Is the domain '" + db.getAttribute(DBATTRIB_DOMAIN) + "' misconfigured?");
}
// Misconfigured domains will no longer result in dropped
// logins
// this.getSessionLogins(session).remove(domain);
}
}
// Attempts to use other login information
// Try to login via session token
if (db.hasFeature(WGDatabase.FEATURE_SESSIONTOKEN)) {
String cookieName = (String) db.getAttribute(WGACore.DBATTRIB_SESSIONCOOKIE);
if (cookieName != null) {
Cookie[] cookies = request.getCookies();
if (cookies != null) { // Can actually happen, especially
// with
// non-browser http clients
Cookie tokenCookie = null;
for (int idx = 0; idx < cookies.length; idx++) {
if (cookies[idx].getName().equals(cookieName)) {
tokenCookie = cookies[idx];
break;
}
}
if (tokenCookie != null) {
db.openSession(WGDatabase.SESSIONTOKEN_USER, tokenCookie.getValue());
if (db.isSessionOpen()) {
// CONSIDERED HARMFUL: Session tokens may
// expire. Safer to always retrieve "fresh" from
// cookie
// loginInfo = new
// DBLoginInfo(WGDatabase.SESSIONTOKEN_USER,
// tokenCookie.getValue());
// this.getSessionLogins(session).put(domainConfig.getName(),
// loginInfo);
return prepareDB(db, request);
}
}
}
}
}
// Try to login by default (HTTP) Login
loginInfo = (DBLoginInfo) session.getAttribute(WGPRequestPath.SESSION_HTTPLOGIN);
if (loginInfo != null) {
db.openSession(loginInfo.getUserName(), loginInfo.getCredentials());
if (db.isSessionOpen()) {
this.getSessionLogins(session).put(domainConfig.getName(), loginInfo);
return prepareDB(db, request);
}
}
// Anonymous login, if nothing else applies. CANNOT BE STORED, bc.
// Sessionlogins may suddenly be available without notice
db.openSession(WGDatabase.ANONYMOUS_USER, null);
return prepareDB(db, request);
}
}
/**
* opens a content db based upon request.getRemoteUser and request.getUserPrincipal()
* if request.getRemoteUser is 'null', WGDatabase.UNKNOWN_REMOTE_USER is given to the authmodule
* @param db
* @param request
* @return
* @throws WGAPIException
* @throws ClientAccessException
*/
private WGDatabase openContentDBRequestBased(WGDatabase db, HttpServletRequest request) throws WGAPIException, ClientAccessException {
if (request == null) {
return prepareDB(db, request);
}
String user = request.getRemoteUser();
if (user == null) {
user = WGDatabase.UNKNOWN_REMOTE_USER;
}
Principal credentials = request.getUserPrincipal();
db.openSession(user, credentials);
if (db.isSessionOpen()) {
// create login info
DBLoginInfo loginInfo = new DBLoginInfo(db.getSessionContext().getUser(), credentials);
this.getSessionLogins(request.getSession()).put(db.getAttribute(DBATTRIB_DOMAIN), loginInfo);
}
return prepareDB(db, request);
}
private WGDatabase openContentDBCertAuth(WGDatabase db, HttpServletRequest request) throws WGException {
if (request == null) {
return prepareDB(db, request);
}
// retrieve certificate chain
X509Certificate certChain[] = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
if (certChain == null || certChain.length < 1) {
getLog().warn("Failed login for client " + request.getRemoteAddr() + " to database " + db.getDbReference() + ": No client certificate chain provided");
return prepareDB(db, request);
}
// retrieve client cert
X509Certificate clientCert = certChain[0];
if (clientCert == null) {
getLog().warn("Failed login for client " + request.getRemoteAddr() + " to database " + db.getDbReference() + ": No client certificate provided");
return prepareDB(db, request);
}
db.openSession(clientCert);
if (db.isSessionOpen()) {
// create login info
// This prevents domains from using mixed cert and regular auth bc. of credential type conflicts
DBLoginInfo loginInfo = new DBLoginInfo(db.getSessionContext().getUser(), clientCert);
this.getSessionLogins(request.getSession()).put(db.getAttribute(DBATTRIB_DOMAIN), loginInfo);
}
return prepareDB(db, request);
}
/**
* checks if domain is enabled for certificate authentication per definition
* a domain is enabled for certauth if - the authmodule configured on
* domainlevel has certauth enabled - or one db in this domain has an
* certauth-enabled authmodule
*
* @param domain
* @return true/false
*/
public boolean certAuthEnabledForDomain(String domain) {
DomainConfiguration domainCfg = getDomainConfig(domain);
if (domainCfg == null) {
return false;
}
if (domainCfg.getAuthenticationSource() instanceof CertAuthCapableAuthModule) {
CertAuthCapableAuthModule certAuthModule = (CertAuthCapableAuthModule) domainCfg.getAuthenticationSource();
return certAuthModule.isCertAuthEnabled();
}
return false;
}
/**
* returns a list with all dbs in the given domain
*
* @param domain
* @return
*/
public List<WGDatabase> getDatabasesForDomain(String domain) {
Iterator<WGDatabase> dbs = this.contentdbs.values().iterator();
ArrayList<WGDatabase> domDbs = new ArrayList<WGDatabase>();
while (dbs.hasNext()) {
WGDatabase db = dbs.next();
if (domain.equals(db.getAttribute(WGACore.DBATTRIB_DOMAIN))) {
domDbs.add(db);
}
}
return domDbs;
}
/**
* returns all databases available within this request (for this user)
*
* @param request
* @return a list of all databases which can be accessed by this request
*/
public List<WGDatabase> openContentDBs(javax.servlet.http.HttpServletRequest request) {
ArrayList<WGDatabase> dbs = new ArrayList<WGDatabase>();
Iterator<String> dbKeys = contentdbs.keySet().iterator();
while (dbKeys.hasNext()) {
String dbKey = dbKeys.next();
WGDatabase db;
try {
db = openContentDB(dbKey, request);
if (db.isSessionOpen()) {
dbs.add(db);
}
}
catch (WGException e) {
// ignore db
}
}
return dbs;
}
/**
* returns all databases available within this request (for this user) which
* contains to domain
*
* @param request
* @param domain
* @return a list of all databases which can be accessed by this request and
* contains to domain
*/
public List<WGDatabase> openContentDBs(javax.servlet.http.HttpServletRequest request, String domain) {
ArrayList<WGDatabase> dbs = new ArrayList<WGDatabase>();
Iterator<String> dbKeys = contentdbs.keySet().iterator();
while (dbKeys.hasNext()) {
String dbKey = dbKeys.next();
try {
WGDatabase db = openContentDB(dbKey, request);
if (db.isSessionOpen()) {
String dbDomain = (String) db.getAttribute(WGACore.DBATTRIB_DOMAIN);
if (dbDomain.equals(domain)) {
dbs.add(db);
}
}
}
catch (WGException e) {
// ignore db
}
}
return dbs;
}
public WGDatabase prepareDB(WGDatabase db, HttpServletRequest request) {
if (db.isSessionOpen()) {
// Check for system file container update if the db's design provider does not notify
if (db.getDesignProvider() != null && !db.getDesignProvider().isNotifying()) {
try {
getSystemContainerManager().checkForUpdates(db);
}
catch (Exception e) {
getLog().error("Exception updating system file container", e);
}
}
// Set some session context attributes
if (request != null) {
db.getSessionContext().setAttribute(WGACore.DBSESSIONCONTEXT_REQUEST, request);
db.getSessionContext().setTask(
"WGA Server " + request.getMethod() + " Request: " + request.getRequestURL().toString());
}
}
return db;
}
public WGDatabase openPersonalisationDB(String domain, javax.servlet.http.HttpSession session) throws WGAPIException {
DomainConfiguration domainCfg = getDomainConfig(domain);
if (domainCfg == null) {
return null;
}
WGDatabase db = this.personalisationdbs.get(domainCfg.getUID());
if (db == null) {
return null;
}
if (!db.isSessionOpen()) {
db.openSession();
}
return db;
}
private File licenseFile;
private Map<String, Class> _customFormatters = Collections.synchronizedMap(new HashMap<String, Class>());
private Map<String, Class> _systemFormatters = Collections.synchronizedMap(new HashMap<String, Class>());
public boolean isMediaKeyDefined(String mediaKey) {
return this.systemMediaKeys.containsKey(mediaKey) || this.customMediaKeys.containsKey(mediaKey);
}
// private String DBATTRIB_LOGGER = ATTRIB_BASE + "Logger";
public void removePersonalisationDB(String domain) {
WGDatabase db = this.personalisationdbs.remove(domain);
if (db == null) {
return;
}
// Notify all managed DB attributes
Iterator attNames = db.getAttributeNames().iterator();
while (attNames.hasNext()) {
Object att = db.getAttribute((String) attNames.next());
if (att instanceof ManagedDBAttribute) {
((ManagedDBAttribute) att).close();
}
}
// Close the database
try {
db.close();
this.log.info("Removed personalisation database for domain \"" + domain + "\"");
}
catch (WGAPIException e) {
this.log.error("Unable to remove personalisation database for domain \"" + domain + "\"", e);
}
}
public class TMLScriptGlobalRegistry {
private Map<String, TMLScriptGlobal> _tmlscriptGlobals = WGUtils.createSynchronizedMap();
public boolean registerGlobal(TMLScriptGlobal scriptGlobal) {
getLog().info("Registering TMLScript Global \"" + scriptGlobal.getName() + "\"");
TMLScriptGlobal previousGlobal = _tmlscriptGlobals.get(scriptGlobal.getName());
_tmlscriptGlobals.put(scriptGlobal.getName(), scriptGlobal);
return true;
}
public boolean registerDBGlobal(TMLScriptGlobal scriptGlobal, WGDatabase db) {
getLog().info("Registering TMLScript DB Global \"" + scriptGlobal.getName() + "\" for database " + db.getDbReference());
Map<String, TMLScriptGlobal> globals = (Map<String, TMLScriptGlobal>) db.getAttribute(WGACore.DBATTRIB_DBGlOBALS);
TMLScriptGlobal previousGlobal = globals.get(scriptGlobal.getName());
globals.put(scriptGlobal.getName(), scriptGlobal);
return true;
}
public TMLScriptGlobal getGlobal(String name, WGDatabase db) {
Map globals = (Map) db.getAttribute(WGACore.DBATTRIB_DBGlOBALS);
TMLScriptGlobal global = (TMLScriptGlobal) globals.get(name);
if (global != null) {
return global;
}
return _tmlscriptGlobals.get(name);
}
public boolean isGlobalDefined(String name, WGDatabase db) {
Map globals = (Map) db.getAttribute(WGACore.DBATTRIB_DBGlOBALS);
boolean contained = globals.containsKey(name);
if (contained) {
return true;
}
return _tmlscriptGlobals.containsKey(name);
}
}
// Tool threads
private WGPDeployer deployer;
private ExternalFileServingConfig _externalFileServingConfig = new ExternalFileServingConfig();
public ExternalFileServingConfig getExternalFileServingConfig() {
return _externalFileServingConfig;
}
public synchronized void removeContentDB(String key) {
WGDatabase db = this.contentdbs.remove(key);
if (db != null) {
/*
* if (db.isSessionOpen()) { db.closeSession(); }
*/
// Deregister from wgacore objects
this._systemContainerManager.removeDatabase(db);
this.deployer.removeLayouts(db);
this.eventManager.removeDatabaseEvents(key);
db.removeDatabaseEventListener(eventManager);
db.removeContentEventListener(eventManager);
db.removeWorkflowEventListener(eventManager);
// Notify all managed DB attributes
Iterator attNames = db.getAttributeNames().iterator();
while (attNames.hasNext()) {
Object att = db.getAttribute((String) attNames.next());
if (att instanceof ManagedDBAttribute) {
((ManagedDBAttribute) att).close();
}
}
// Clear WebTML cache
try {
getWebTMLCache().clearForDatabase(key);
}
catch (CacheException e1) {
log.error("Exception clearing WebTML cache for closing db '" + key + "'", e1);
}
// Call event
fireCoreEvent(new WGACoreEvent(WGACoreEvent.TYPE_CS_DISCONNECTED, db, this));
// we might have to remove hdb instance
WGHierarchicalDatabase.removeInstance(db.getDbReference());
// Close an external personalisation db if there is one
if (db.hasAttribute(DBATTRIB_EXTERNAL_SELF_PERSONALISATION_DB)) {
try {
WGDatabase persdb = (WGDatabase) db.getAttribute(DBATTRIB_EXTERNAL_SELF_PERSONALISATION_DB);
persdb.close();
}
catch (WGAPIException e) {
log.error("Exception closing external personalisation database for db '" + key + "'", e);
}
}
// Close the database itself
try {
db.close();
this.log.info("Closed content database for key \"" + key + "\"");
}
catch (WGAPIException e) {
log.error("Unable to close content database for key \"" + key + "\"", e);
}
}
}
public void removeCustomShare(String name) {
ShareDefinition def = getShares().get(name);
if (def == null) {
getLog().info("Cannot remove custom share '" + def.getName() + "'. It does not exist.");
}
else if (def.getOrigin() != ShareDefinition.ORIGIN_CUSTOM) {
getLog().info("Cannot remove custom share '" + def.getName() + "'. It is not custom.");
}
getShares().remove(name);
getLog().info("Removed custom share '" + name + "'");
}
public static final String DBATTRIB_LOGGER = "Logger";
public static final String DBATTRIB_DESIGNSYNC = "designsync";
/**
* Sets, if this database should be regarded a db with multilanguage content
* (true) where the language should get selected by the users preferences,
* or if all requests for content should retrieve the database's default
* language (false)
*/
public static final String DBATTRIB_MULTILANGUAGE_CONTENT = "MultiLanguageContent";
private static final String DBATTRIB_FIRSTLEVELDBOPTIONS = "FirstLevelDBOptions";
public static final String DBATTRIB_FIRSTLEVELPUBLISHEROPTIONS = "FirstLevelPublisherOptions";
public static final String DBATTRIB_FULLY_CONNECTED = "FullyConnected";
public static final String DBATTRIB_DBGlOBALS = "TMLScriptDBGlobals";
private static final String CACHENAME_DESIGNFILES = "DesignFiles";
public static final String DBATTRIB_EXTERNAL_SELF_PERSONALISATION_DB = "ExternalSelfPersonalisationDB";
public static final String DBATTRIB_FORCE_LABEL_LANGUAGE = "ForceLabelLanguage";
public static final String DBATTRIB_FALLBACK_LABEL_LANGUAGE = "FallbackLabelLanguage";
private WGDatabase retrieveContentDB(ContentDatabase config, Map<String, Serializable> dbConnectionFailures) {
String dbType = (config instanceof ContentStore ? "Web application" : "Data source");
if (config instanceof ContentStore) {
logCategoryInfo(dbType + " " + config.getKey(), 2);
}
else {
logCategoryInfo(dbType + " " + config.getKey(), 2);
}
// Get basic information
String strType = config.getImplClassName();
String strKey = config.getKey();
// retrieve dbserver for db
WGDatabaseServer server = getDatabaseServers().get(config.getDbServer());
if (server == null) {
log.error("Could not open database for key " + strKey.toLowerCase() + ": The server " + config.getDbServer() + " is unknown");
return null;
}
// TODO this should be done in configuration validation not here
if (strKey.equalsIgnoreCase("start") || strKey.equalsIgnoreCase("bi") || strKey.equalsIgnoreCase("static") || strKey.equalsIgnoreCase("statictml")) {
String message = "Cannot map " + dbType + " to key \"" + strKey + "\" - This is a predefined key not available for content databases";
log.error(message);
dbConnectionFailures.put(strKey, message);
return null;
}
// TODO this should be done in configuration validation not here
if (strKey.startsWith(PluginConfig.PLUGIN_DBKEY_PREFIX)) {
String message = "Cannot map " + dbType + " to key \"" + strKey + "\" - The key prefix \"" + PluginConfig.PLUGIN_DBKEY_PREFIX + "\" is reserved for WGA plugins";
log.error(message);
dbConnectionFailures.put(strKey, message);
return null;
}
// Look if the server is able and allowed to instantiate this db type
Class<WGDatabaseCore> typeClass;
try {
Class theClass = WGFactory.getImplementationLoader().loadClass(strType);
if (!WGDatabaseCore.class.isAssignableFrom(theClass)) {
String message = "Cannot map " + dbType + " to key \"" + strKey + "\" - Database implementation class \"" + strType + "\" is no WGDatabaseCore implementation.";
return null;
}
typeClass = theClass;
}
catch (ClassNotFoundException e) {
String message = "Cannot map " + dbType + " to key \"" + strKey + "\" - Database implementation class \"" + strType + "\" not available.";
log.error(message);
dbConnectionFailures.put(strKey, message);
return null;
}
catch (NoClassDefFoundError e) {
String message = "Cannot map " + dbType + " to key \"" + strKey + "\" - Database implementation class or dependent class for type \"" + strType + "\" not found: \"" + e.getMessage();
log.error(message);
dbConnectionFailures.put(strKey, message);
return null;
}
catch (VerifyError e) {
String message = "Cannot map " + dbType + "to key \"" + strKey + "\" - Verify error: " + e.getMessage();
log.error(message);
dbConnectionFailures.put(strKey, message);
return null;
}
if (!isDBAllowed(typeClass, strKey)) {
String message = "Cannot map " + dbType + " to key \"" + strKey + "\" - Your server license type is not allowed to use this database type";
log.error(message);
dbConnectionFailures.put(strKey, message);
return null;
}
// Evaluate title
String title = config.getTitle();
// Evaluate domain
/*
Element domainElement = (Element) databaseElement.selectSingleNode("domain");
DomainConfiguration domainConfig = new DomainConfiguration();
if (domainElement != null) {
domainConfig = getDomainConfig(domainElement.getStringValue());
}*/
Domain domain = getWgaConfiguration().getDomain(config.getDomain());
DomainConfiguration domainConfig = getDomainConfig(domain);
// Collect db options from global, server, database
HashMap<String, String> dbOptions = new HashMap<String, String>();
dbOptions.put(WGDatabase.COPTION_USERCACHELATENCY, String.valueOf(_wgaConfiguration.getUserCacheLatencyMinutes()));
dbOptions.putAll(_globalDbOptions);
dbOptions.putAll(config.getDatabaseOptions());
// We collect those options that were added on database level in here
// and add this set as database attribute
// so we can tell them later from lower priority options
Set<String> firstLevelDBOptions = new HashSet<String>();
firstLevelDBOptions.addAll(config.getDatabaseOptions().keySet());
// Mandatory db options
dbOptions.put(WGDatabase.COPTION_DBREFERENCE, strKey.toLowerCase());
// get the database object
WGDatabase db = null;
try {
if (config.isLazyConnecting()) {
db = server.prepareDatabase(typeClass, dbOptions);
}
else {
db = server.openDatabase(typeClass, dbOptions);
}
}
catch (Throwable e1) {
String message = "Could not open database for key " + strKey.toLowerCase();
log.error(message, e1);
dbConnectionFailures.put(strKey, e1);
return null;
}
if (db == null || (!config.isLazyConnecting() && !db.isSessionOpen())) {
log.error("Could not open database for key " + strKey.toLowerCase() + " - Check logged messages above for error details");
dbConnectionFailures.put(strKey, "Could not open database for key " + strKey.toLowerCase() + " - Check wga log for details");
return null;
}
if (!config.isLazyConnecting()) {
db.getSessionContext().setTask("Initializing database in WGA");
log.info("Mapping " + dbType + " on path \"" + db.getPath() + "\" (" + db.getTypeName() + ") to database key \"" + strKey.toLowerCase() + "\"");
try {
if (db.getContentStoreVersion() != WGDatabase.CSVERSION_NO_CONTENTSTORE) {
log.info("Database for " + strKey.toLowerCase() + " is a WGA Content Store of version " + db.getContentStoreVersion());
}
}
catch (WGAPIException e) {
log.error("Exception determining content store version of database " + strKey.toLowerCase(), e);
}
}
else {
log.info("Preparing " + dbType + " on path \"" + db.getPath() + "\" (" + db.getTypeName() + ") as database for key \"" + strKey.toLowerCase() + "\"");
}
if (title != null) {
db.setTitle(title);
}
// Inject the default language if configured, else trigger determination
if (config instanceof ContentStore) {
ContentStore csConfig = (ContentStore) config;
if (!WGUtils.isEmpty(csConfig.getDefaultLanguage())) {
db.setDefaultLanguage(csConfig.getDefaultLanguage());
}
else {
try {
db.determineDefaultLanguage();
}
catch (WGAPIException e) {
getLog().error("Exception determining default language for " + dbType + " " + db.getDbReference(), e);
}
}
}
// Set mandatory database attributes
initializeDBAttributes(db, strKey, domainConfig.getName(), firstLevelDBOptions);
// Inject domain authentication module
if (domainConfig.getAuthModule() != null) {
try {
db.setAuthenticationModule(new DomainRedirectionAuthModule(this, domainConfig.getName()));
}
catch (WGIllegalArgumentException e) {
String message = "Exception setting authentication module of " + dbType + " '" + strKey + "'";
getLog().error(message, e);
getLog().error("Cancelling connection of " + dbType + " '" + strKey + "' because the configured authentication could not be set");
dbConnectionFailures.put(strKey, message);
try {
db.close();
}
catch (Exception e2) {
}
return null;
}
}
// Configure design provider, if neccessary
if (config instanceof ContentStore) {
ContentStore csConfig = (ContentStore) config;
if (csConfig.getDesign() != null) {
getDesignManager().applyDesign(db, csConfig);
}
}
// Determine if ACL is empty
// If so, eventually add domain default manager
boolean aclEmpty = false;
try {
if (db.isConnected() && db.isSessionOpen() && db.hasFeature(WGDatabase.FEATURE_ACL_MANAGEABLE) && db.getACL().getAllEntries().size() == 0) {
aclEmpty = true;
}
}
catch (WGBackendException e1) {
getLog().error("Error retrieving ACL state of " + dbType + " '" + db.getDbReference() + "'", e1);
}
if (aclEmpty && domainConfig.getDefaultManager() != null) {
try {
getLog().info("Adding default manager '" + domainConfig.getDefaultManager() + "' to ACL of '" + strKey + "'");
db.getACL().createUserEntry(domainConfig.getDefaultManager(), WGDatabase.ACCESSLEVEL_MANAGER);
}
catch (WGAPIException e) {
getLog().error("Exception on adding default manager to ACL of '" + strKey + "'", e);
}
}
// Process system container
SystemContainerManager.SystemContainerContext scContext = null;
try {
scContext = _systemContainerManager.addDatabase(db, aclEmpty);
}
catch (InvalidCSConfigVersionException e) {
this.log.error("Unable to process system file container. The design of " + dbType + " '" + db.getDbReference() + "' was developed for a higher WGA version: " + e.getTargetVersion());
}
catch (Exception e) {
this.log.error("Exception processing system file container for " + dbType + " '" + strKey.toLowerCase() + "'", e);
}
// Merge publisher options from global, server, design, database
Map<String, String> publisherOptions = new HashMap<String, String>();
publisherOptions.putAll(_globalPublisherOptions);
if (scContext != null) {
scContext.putPublisherOptions(publisherOptions);
}
publisherOptions.putAll(config.getPublisherOptions());
// We collect those options that were added on database level in here
// and add this set as database attribute
// so we can tell them later from lower priority options
Set<String> firstLevelPublisherOptions = new HashSet<String>();
firstLevelPublisherOptions.addAll(config.getPublisherOptions().keySet());
db.setAttribute(DBATTRIB_FIRSTLEVELPUBLISHEROPTIONS, firstLevelPublisherOptions);
// Publisher options initialisation, which is equal for content dbs and plugins
processPublisherOptions(db, publisherOptions);
// check if db is empty before hdb script runs
boolean isEmptyDB = false;
try {
isEmptyDB = (db.isConnected() && db.hasFeature(WGDatabase.FEATURE_FULLCONTENTFEATURES) && db.isContentEmpty());
} catch (WGAPIException e) {
this.log.error("Unable to check if database '" + db.getDbReference() + "' is empty.", e);
}
// Validate default language definition
if (!isEmptyDB && db.hasFeature(WGDatabase.FEATURE_FULLCONTENTFEATURES)) {
db.onConnect(new ValidateDefaultLanguageAction());
}
// Eventually prepare "external self-personalisation"
if (db.hasFeature(WGDatabase.FEATURE_FULLCONTENTFEATURES) && domainConfig.getPersonalisation() == null && !db.hasFeature(WGDatabase.FEATURE_SELF_PERSONALIZABLE)) {
try {
createExternalSelfPersonalisation(db);
}
catch (WGAPIException e) {
this.log.error("Exception creating external personalisation database for db '" + db.getDbReference() + "'. Profiles will not be available.", e);
}
}
// Do system container initialisations
if (scContext != null) {
scContext.performInitialisation(new Boolean(isEmptyDB));
// Revalidate the default language if the database was empty before initialisation, might have new definitions now
if (isEmptyDB) {
db.onConnect(new ValidateDefaultLanguageAction());
}
}
// Mark this database as fully connected
db.setAttribute(DBATTRIB_FULLY_CONNECTED, "true");
if (_externalFileServingConfig.isEnabled() && db.getBooleanAttribute(DBATTRIB_EXTERNAL_FILE_SERVING_ENABLED, false)) {
getLog().info("External file serving enabled for database '" + db.getDbReference() + "'.");
}
return db;
}
private void createExternalSelfPersonalisation(WGDatabase db) throws WGAPIException {
File dbDir = new File(getWgaDataDir(), EXTERNAL_PERSDBS_FOLDER);
if (!dbDir.exists()) {
dbDir.mkdir();
}
Map<String, String> dbOptions = new HashMap<String, String>();
dbOptions.put(WGDatabase.COPTION_DBREFERENCE, db.getDbReference() + "$pers");
dbOptions.put(WGDatabase.COPTION_READERPROFILECREATION, "true");
dbOptions.put(WGDatabase.COPTION_USERCACHELATENCY, String.valueOf(_wgaConfiguration.getUserCacheLatencyMinutes()));
dbOptions.put(WGDatabase.COPTION_WORKFLOWENGINE, WGDefaultWorkflowEngine.class.getName()); // We do not want any real workflow here
WGDatabase persdb = WGFactory.getInstance().openDatabase(null, de.innovationgate.webgate.api.hsql.WGDatabaseImpl.class.getName(), dbDir.getPath() + "/" + db.getDbReference(), "sa", "", dbOptions);
db.setAttribute(DBATTRIB_EXTERNAL_SELF_PERSONALISATION_DB, persdb);
}
private DomainConfiguration getDomainConfig(Domain domain) {
return getDomainConfig(domain.getName());
}
private void initializeDBAttributes(WGDatabase db, String dbKey, String domainName, Set firstLevelDBOptions) {
db.setAttribute(DBATTRIB_DBKEY, dbKey.toLowerCase());
db.setAttribute(DBATTRIB_DOMAIN, domainName);
db.setAttribute(DBATTRIB_FIRSTLEVELDBOPTIONS, firstLevelDBOptions);
db.setAttribute(DBATTRIB_DBGlOBALS, WGUtils.createSynchronizedMap());
Iterator defaultAtts = _dbDefaultAttributes.entrySet().iterator();
while (defaultAtts.hasNext()) {
Map.Entry entry = (Map.Entry) defaultAtts.next();
db.setAttribute((String) entry.getKey(), (String) entry.getValue());
}
}
public File getWGAFile(String fileName) {
// Path variables
fileName = replaceWGAPathVariables(fileName);
// Dir links
File file = WGUtils.resolveDirLink(new File(fileName));
// First try: Use as absolute path
if (file.exists()) {
return file;
}
// Second try: Find inside wgaconfig path
File wgaConfigPath = configFile.getParentFile();
file = new File(wgaConfigPath, fileName);
if (file.exists()) {
return file;
}
else {
return null;
}
}
public String replaceWGAPathVariables(String fileName) {
return WGUtils.strReplace(fileName, "${", _replaceProcessorInstance, true);
}
public File getWGAFolder(String fileName) {
return getWGAFile(fileName);
}
public File getOrCreateWGAFolder(String fileName) {
// Path variables
fileName = replaceWGAPathVariables(fileName);
// Dir links
File file = WGUtils.resolveDirLink(new File(fileName));
// First try: Use as absolute path
if (file.exists()) {
return file;
} else if (file.isAbsolute()) {
file.mkdir();
if (file.exists() && file.isDirectory()) {
return file;
} else {
return null;
}
}
// Second try: Find inside wgaconfig path
File wgaConfigPath = configFile.getParentFile();
file = new File(wgaConfigPath, fileName);
if (file.exists()) {
return file;
}
else {
file.mkdir();
if (file.exists() && file.isDirectory()) {
return file;
} else {
return null;
}
}
}
public WGDatabase retrievePersonalisationDB(Domain domainConfig) {
PersonalisationDatabase config = domainConfig.getPersonalisation();
// Get basic information
String strType = config.getImplClassName();
// Look if impl class is reachable
Class<WGDatabaseCore> typeClass;
try {
Class theClass = Class.forName(strType, true, WGFactory.getImplementationLoader());
if (!WGDatabaseCore.class.isAssignableFrom(theClass)) {
String message = "Cannot connect personalisation database for domain \"" + domainConfig.toString() + "\" - Database implementation class \"" + strType + "\" is no WGDatabaseCore implementation.";
return null;
}
typeClass = theClass;
}
catch (ClassNotFoundException e) {
log.error("Cannot attach personalisation database to domain \"" + domainConfig.toString() + "\" - Database implementation class \"" + strType + "\" not available.");
return null;
}
catch (NoClassDefFoundError e) {
log.error("Cannot attach personalisation database to domain \"" + domainConfig.toString() + "\" - Database implementation class or dependent class for type \"" + strType + "\" not found: \""
+ e.getMessage());
return null;
}
catch (VerifyError e) {
log.error("Cannot attach personalisation database to domain \"" + domainConfig.toString() + "\" - Verify error: " + e.getMessage());
return null;
}
// Look if license allows it
if (!isPersonalisationDBAllowed(typeClass, domainConfig.getUid())) {
log.error("Cannot attach personalisation database to domain \"" + domainConfig.toString() + "\" - Your server license type is not allowed to use this database type");
return null;
}
// Retrieve server
WGDatabaseServer server = getDatabaseServers().get(config.getDbServer());
if (server == null) {
log.error("Could not open personalisation database for domain '" + domainConfig.toString() + "': The server " + config.getDbServer() + " is unknown");
return null;
}
// Merge db options from global, server, database
HashMap<String, String> dbOptions = new HashMap<String, String>();
dbOptions.putAll(_globalDbOptions);
dbOptions.putAll(server.getOptions());
dbOptions.putAll(config.getDatabaseOptions());
// Mandatory db options
dbOptions.put(WGDatabase.COPTION_DBREFERENCE , "personalisation_" + domainConfig.getUid());
// get the database object
WGDatabase db = null;
try {
if (config.isLazyConnecting()) {
db = server.prepareDatabase(typeClass, dbOptions);
}
else {
db = server.openDatabase(typeClass, dbOptions);
}
}
catch (WGAPIException e) {
getLog().error("Could not connect to database: " + e.getMessage());
}
catch (ModuleDependencyException e) {
getLog().error("Could not connect to database because of missing dependency: " + e.getMessage());
}
if (db == null) {
log.error("Could not open personalisation database for domain '" + domainConfig.getName() + " - Check logged messages above for error details");
return null;
}
else if (!db.getRoles().contains(WGDatabase.ROLE_USERPROFILES)) {
log.error("Could not open personalisation database \for domain '" + domainConfig.getName() + " - This type does not deliver user profiles");
return null;
}
if (config.isLazyConnecting()) {
log.info("Preparing personalisation database on path \"" + db.getPath() + "\" for domain \"" + domainConfig.getName() + "\"");
db.addDatabaseConnectListener(this);
}
else {
log.info("Attaching personalisation database on path \"" + db.getPath() + "\" to domain \"" + domainConfig.getName() + "\"");
try {
log.info("Personalisation database of domain " + domainConfig.getName() + " is content store version " + db.getContentStoreVersion());
}
catch (WGAPIException e) {
log.error("Exception determining content store version of personalisation database for domain " + domainConfig.getName(), e);
}
}
// Set domain
db.setAttribute(WGACore.DBATTRIB_DOMAIN, domainConfig.getUid());
// Mark this database as fully connected
db.setAttribute(DBATTRIB_FULLY_CONNECTED, "true");
return db;
}
public class ConfigUpdateTask extends TimerTask {
private WGACore _core;
public ConfigUpdateTask(WGACore core) {
_core = core;
}
/**
* @see java.lang.Runnable#run()
*/
public void run() {
Thread.currentThread().setName("WGA.MainTimer");
try {
synchronized(WGACore.this) {
if (_core.configFile.lastModified() > _core.configFileLastModified) {
_core.updateConfig();
}
}
}
catch (Exception e) {
Logger.getLogger("wga").error("Error updating configuration", e);
}
}
}
private ServletContext _context;
protected int tmlBuffer = 8;
protected String tmlHeader = "";
private boolean profilingEnabled = false;
private Map<String, ShareDefinition> _shares = new HashMap<String, ShareDefinition>();
/**
*
* @param deploy
* @return set containing dbkeys which where initial connected in this
* configUpdate
*/
public synchronized void updateContentDBs(boolean deploy) {
// contains dbkeys that where initial connected in this configUpdate
HashSet<String> newConnectedDBKeys = new HashSet<String>();
WGFactory.getInstance().closeSessions();
//Element databaseRoot = (Element) this.configDocument.getRootElement().selectSingleNode("contentdbs");
//List databaseElements = databaseRoot.selectNodes("contentdb");
//Element databaseElement;
ContentDatabase databaseConfig;
WGDatabase db;
Set<String> currentDBs = new HashSet<String>();
// db connection errors mapped by dbkey
Map<String, Serializable> dbConnectionFailures = new HashMap<String, Serializable>();
List<ContentDatabase> databases = _wgaConfiguration.getContentDatabases();
// Map new databases and update current databases
for (int idxDB = 0; idxDB < databases.size(); idxDB++) {
databaseConfig = databases.get(idxDB);
String dbKey = databaseConfig.getKey();
// ignore disabled dbs
if (!databaseConfig.isEnabled()) {
continue;
}
DatabaseServer serverConfig = (DatabaseServer) _wgaConfiguration.getByUid(databaseConfig.getDbServer());
if (serverConfig != null && !serverConfig.isEnabled()) {
continue;
}
// Get or create database object
boolean isNewDB = false;
if (this.contentdbs.containsKey(dbKey) == false) {
try {
db = retrieveContentDB(databaseConfig, dbConnectionFailures);
if (db == null) {
continue;
}
this.contentdbs.put(dbKey, db);
isNewDB = true;
newConnectedDBKeys.add(dbKey);
}
catch (Throwable e) {
getLog().error("Exception connecting database " + dbKey, e);
if (this.contentdbs.containsKey(dbKey)) {
this.contentdbs.remove(dbKey);
}
continue;
}
}
else {
db = this.contentdbs.get(dbKey);
}
currentDBs.add(dbKey);
// Update stored queries
/*
Element queryRoot = (Element) databaseElement.selectSingleNode("storedqueries");
if (queryRoot != null) {
updateStoredQueries(db, queryRoot);
}*/
// Update field mappings
/*
Element mappingRoot = (Element) databaseElement.selectSingleNode("fieldmappings");
if (mappingRoot != null) {
}*/
updateFieldMappings(db, databaseConfig.getFieldMappings());
// Update client restrictions
if (databaseConfig.isClientRestrictionsEnabled()) {
db.setAttribute(DBATTRIB_CLIENTRESTRICTIONS, IPv4Restriction.getRestrictions(databaseConfig.getClientRestrictions(), databaseConfig.getKey(), getLog()));
} else {
// if not enabled remove clientRestrictions from db
db.removeAttribute(DBATTRIB_CLIENTRESTRICTIONS);
}
// Operations only for newly connected databases
if (isNewDB) {
performNewDBOperations(db);
}
}
// Unmap removed databases
Set<String> removedDBs = new HashSet<String>(this.contentdbs.keySet());
removedDBs.removeAll(currentDBs);
Iterator<String> removedIt = removedDBs.iterator();
while (removedIt.hasNext()) {
String key = removedIt.next();
if (!key.startsWith(PluginConfig.PLUGIN_DBKEY_PREFIX)) {
removeContentDB(key);
}
}
// notify LuceneManager
if (luceneManager != null) {
luceneManager.configurationHasChanged(newConnectedDBKeys);
}
// inform admin of connection errors
if (!dbConnectionFailures.isEmpty()) {
WGAMailNotification notification = new WGAMailNotification(WGAMailNotification.TYPE_DATABASE_INITIALISATION_ERRORS);
notification.setSubject("Some databases could not be initialized successfully");
notification.append("<b>The follwing databases has reported errors during initialisation:</b>");
Iterator<String> dbkeys = dbConnectionFailures.keySet().iterator();
while (dbkeys.hasNext()) {
String dbkey = dbkeys.next();
notification.append("<br><br><b>Database:</b> " + dbkey + "<br>");
Object failure = dbConnectionFailures.get(dbkey);
if (failure instanceof String) {
notification.append((String)failure);
} else if (failure instanceof Throwable) {
Throwable throwable = (Throwable) failure;
if (throwable != null) {
notification.append(throwable);
}
}
}
notification.setAttachLogfile(true);
send(notification);
}
}
private void updateShares() {
// Add all shares from configuration
Iterator<Share> shareConfigs = getWgaConfiguration().getShares().iterator();
Map<String, ShareDefinition> newShares = new HashMap<String, ShareDefinition>();
while (shareConfigs.hasNext()) {
Share shareConfig = shareConfigs.next();
if (!shareConfig.isEnabled()) {
continue;
}
ModuleDefinition shareModDefinition = getModuleRegistry().getModuleDefinition(ShareModuleType.class, shareConfig.getImplClassName());
if (shareModDefinition == null) {
getLog().error("Unknown content share type '" + shareConfig.getImplClassName() + "'");
continue;
}
ShareProperties props = (ShareProperties) shareModDefinition.getProperties();
try {
ShareDefinition shareDefinition = props.createShareDefinition(shareConfig);
shareDefinition.setOrigin(ShareDefinition.ORIGIN_WGACONFIG);
getLog().info("Initializing content share '" + shareConfig.getName() + "'");
shareDefinition.init(this);
newShares.put(shareConfig.getName(), shareDefinition);
}
catch (ShareInitException e) {
getLog().error("Unable to initialize content share '" + shareConfig.getName() + "' because of the following errors:");
Iterator msgs = e.getDetailMessages().iterator();
while (msgs.hasNext()) {
getLog().error("- " + msgs.next());
}
}
catch (Exception e) {
getLog().error("Exception initializing content share '" + shareConfig.getName() + "'", e);
}
}
// Add custom shares that were added to the previous share configs
if (_shares != null) {
Iterator<Map.Entry<String,ShareDefinition>> previousConfigs = _shares.entrySet().iterator();
while (previousConfigs.hasNext()) {
Map.Entry<String,ShareDefinition> shareEntry = previousConfigs.next();
ShareDefinition config = (ShareDefinition) shareEntry.getValue();
if (config.getOrigin() == ShareDefinition.ORIGIN_CUSTOM) {
newShares.put(shareEntry.getKey(), config);
}
}
}
// Set new shares map
_shares = newShares;
}
private void performNewDBOperations(WGDatabase db) {
// When lazily connected: register for database connection event
// to load events and show a message when it happens
if (!db.isConnected()) {
db.addDatabaseConnectListener(this);
}
// Add listeners for events and register embedded event scripts
db.addDatabaseEventListener(eventManager);
db.addContentEventListener(eventManager);
db.addWorkflowEventListener(eventManager);
if (db.isConnected()) {
eventManager.updateDatabaseEvents(db);
}
// Call content store connection event
fireCoreEvent(new WGACoreEvent(WGACoreEvent.TYPE_CS_CONNECTED, db, this));
}
protected void updateFieldMappings(WGDatabase db, List<FieldMapping> fieldMappings) {
Map<String, String> metaMappings = null;
Map<String, String> itemMappings = null;
Map pluginShortcuts = null;
// Get the mapping maps from containers
boolean dbMappingRoot = false;
metaMappings = (Map<String, String>) db.getAttribute(DBATTRIB_META_MAPPINGS);
itemMappings = (Map<String, String>) db.getAttribute(DBATTRIB_ITEM_MAPPINGS);
pluginShortcuts = (Map) db.getAttribute(DBATTRIB_PLUGIN_SHORTCUTS);
dbMappingRoot = true;
// Mappings that only apply to whole dbs
if (dbMappingRoot == true) {
buildDesignShortcuts(db);
}
if (fieldMappings != null) {
Iterator<FieldMapping> mappings = fieldMappings.iterator();
while (mappings.hasNext()) {
FieldMapping mapping = mappings.next();
if (mapping.getType().equals(FieldMapping.TYPE_META)) {
metaMappings.put(mapping.getName(), mapping.getExpression());
} else if (mapping.getType().equals(FieldMapping.TYPE_ITEM)) {
itemMappings.put(mapping.getName(), mapping.getExpression());
}
}
}
}
protected void buildDesignShortcuts(WGDatabase db) {
Map metaMappings = (Map) db.getAttribute(DBATTRIB_META_MAPPINGS);
Map itemMappings = (Map) db.getAttribute(DBATTRIB_ITEM_MAPPINGS);
Map pluginShortcuts = (Map) db.getAttribute(DBATTRIB_PLUGIN_SHORTCUTS);
CSConfig csconfig = (CSConfig) db.getAttribute(DBATTRIB_CSCONFIG);
if (csconfig != null && csconfig instanceof de.innovationgate.wga.common.beans.csconfig.v2.CSConfig) {
de.innovationgate.wga.common.beans.csconfig.v2.CSConfig v2 = (de.innovationgate.wga.common.beans.csconfig.v2.CSConfig) csconfig;
Iterator shortcuts = v2.getShortcuts().iterator();
while (shortcuts.hasNext()) {
Shortcut shortcut = (Shortcut) shortcuts.next();
if (shortcut.getType() == Shortcut.TYPE_ITEM_MAPPING ||
shortcut.getType() == Shortcut.TYPE_META_MAPPING ||
shortcut.getType() == Shortcut.TYPE_PLUGIN) {
Map<String, String> mappings = (Map<String, String>) (shortcut.getType() == Shortcut.TYPE_ITEM_MAPPING ? itemMappings :
shortcut.getType() == Shortcut.TYPE_META_MAPPING ? metaMappings :
pluginShortcuts);
mappings.put(shortcut.getShortcut(), shortcut.getReference());
}
}
}
}
public synchronized void updatePersonalisationDBs() {
WGFactory.getInstance().closeSessions();
// Map new and update existing databases
Set<String> currentDBs = new HashSet<String>();
Iterator<Domain> domains = _wgaConfiguration.getDomains().iterator();
while (domains.hasNext()) {
Domain domain = domains.next();
PersonalisationDatabase persDBConfig = domain.getPersonalisation();
// Ignore disabled pers databases
if (persDBConfig == null) {
continue;
}
if (!persDBConfig.isEnabled()) {
continue;
}
DatabaseServer serverConfig = (DatabaseServer) _wgaConfiguration.getByUid(persDBConfig.getDbServer());
if (serverConfig != null && !serverConfig.isEnabled()) {
continue;
}
// Get or retrieve db
WGDatabase db = null;
if (this.personalisationdbs.containsKey(domain.getUid())) {
db = this.personalisationdbs.get(domain.getUid());
}
else {
db = retrievePersonalisationDB(domain);
if (db == null) {
continue;
}
this.personalisationdbs.put(domain.getUid(), db);
}
currentDBs.add(domain.getUid());
}
// Unmap removed databases
Set<String> removedDBs = new HashSet<String>(this.personalisationdbs.keySet());
removedDBs.removeAll(currentDBs);
Iterator<String> removedIt = removedDBs.iterator();
while (removedIt.hasNext()) {
String domain = removedIt.next();
removePersonalisationDB(domain);
}
}
private String defaultMediaKey = null;
private static boolean _finalBuild;
private static String _buildSignature;
private Cache _calledSequenceIds = null;
private static Map<String, String> _dbDefaultAttributes = new HashMap<String, String>();
private static Set<String> _licenseFreeDatabases = new HashSet<String>();
static {
// Init the default db attributes for content stores
_dbDefaultAttributes.put(WGACore.DBATTRIB_QUERY_DEFAULT, "native");
_dbDefaultAttributes.put(WGACore.DBATTRIB_EXPRESSION_DEFAULT, "tmlscript");
_dbDefaultAttributes.put(WGACore.DBATTRIB_DEFAULT_MEDIAKEY, ENCODER_HTML);
_dbDefaultAttributes.put(WGACore.DBATTRIB_DEFAULT_ITEM_ENCODING, "none");
_dbDefaultAttributes.put(WGACore.DBATTRIB_MULTILANGUAGE_CONTENT, "true");
_dbDefaultAttributes.put(WGACore.DBATTRIB_HOME_PAGE, "");
_dbDefaultAttributes.put(WGACore.DBATTRIB_LOGIN_PAGE, "");
// Init the license-free database keys
_licenseFreeDatabases.add("plugin-management");
}
private File wgaTempDir = null;
private LuceneManager luceneManager = null;
private Map<String, Analyzer> analyzerMappings = Collections.synchronizedMap(new HashMap<String, Analyzer>());
private Analyzer defaultAnalyzer = new StandardAnalyzer();
// lucene filehandler mapped by file-extension e.g. 'pdf', 'txt', 'xml'
private Map<String, FileHandler> fileHandlerMappings = Collections.synchronizedMap(new HashMap<String, FileHandler>());
// filter mappings for custom javax.servlet.filters
private List<WGAFilterConfig> filterMappings = new LinkedList<WGAFilterConfig>();
private UserAgentVerifier userAgentVerifier;
private DESEncrypter desEncrypter;
private List<WGACoreEventListener> eventListeners = Collections.synchronizedList(new LinkedList<WGACoreEventListener>());
// TestCore for test facility (assertions via tml:script)
private TestCore _testCore;
private DesignFileValidator designFileValidator;
private boolean _webserviceEnabled;
/**
* character encoding used by this wga instance used for request encoding,
* file upload encoding, encoding of deployed tmls, etc.
*/
private String _characterEncoding = null;
private WGAUsageStatistics _usageStatistics;
private Set customCoreListenerClassnames;
private static IsolatedJARLoader baseLibraryLoader;
private Map<String, String> _globalDbOptions;
private Map<String, String> _globalPublisherOptions;
private JmxManager _wgaMonitor;
private LogServer _logServer;
private ResourceConfiguration _resourceConfiguration;
private WGAMailConfiguration _mailConfig;
private Cache designFileCache;
private WebTMLCache _webTMLCache = null;
private void initReadGeneralConfig(boolean update) throws CacheException {
// WGAPI Data Cache
int dataCache = _wgaConfiguration.getWgapiDataCacheSize();
if (dataCache != WGFactory.getInstance().getCacheCapacity()) {
getLog().info("WGAPI Data Cache Capacity is set to " + dataCache + " entries" + (WGFactory.getInstance().isCacheInitialized() ? " (ineffective until a WGAPI data cache reset)" : ""));
WGFactory.getInstance().setCacheCapacity(dataCache);
}
// WebTML Cache
int tmlCache = _wgaConfiguration.getWebtmlCacheSize();
if (_webTMLCache == null) {
_webTMLCache = new WebTMLCache(tmlCache);
getLog().info("WebTML Cache Capacity is set to " + tmlCache + " entries");
}
else if (_webTMLCache.getCapacity() != tmlCache){
_webTMLCache.setCapacity(tmlCache);
getLog().info("WebTML Cache Capacity is set to " + tmlCache + " entries (ineffective until a WebTML cache reset)");
}
_webserviceEnabled = _wgaConfiguration.isWebservicesEnabled();
_characterEncoding = _wgaConfiguration.getCharacterEncoding();
if (_characterEncoding == null) {
_characterEncoding = "UTF-8";
}
log.info("Using default output encoding '" + _characterEncoding + "'.");
tmlBuffer = _wgaConfiguration.getTmlBuffer();
if (_wgaConfiguration.getTmlHeader() != null) {
tmlHeader = _wgaConfiguration.getTmlHeader();
} else {
tmlHeader = "";
}
// determine if character encoding changed
// this is used for SC_NOT_MODIFIED in WGPDispatcher
if (_characterEncoding != null && getLastCharacterEncoding() == null || !getLastCharacterEncoding().equals(_characterEncoding)) {
// character encoding was not yet set or has changed
setLastCharacterEncoding(_characterEncoding);
}
// application log
this.log.setLevel(org.apache.log4j.Level.toLevel(_wgaConfiguration.getApplicationLogLevel()));
if (_wgaConfiguration.getApplicationLogDirectory() != null) {
File loggingDir = new File(_wgaConfiguration.getApplicationLogDirectory());
if (loggingDir.exists()) {
try {
Appender fileAppender = new DailyRollingFileAppender(new PatternLayout("%d{HH:mm:ss} %p %m\n"), loggingDir.getAbsolutePath() + "/" + "wga.log", "yyyy-MM-dd");
this.log.addAppender(fileAppender);
}
catch (IOException e) {
this.log.error("Error creating application log file", e);
}
}
else {
this.log.error("Logging directory " + loggingDir.getAbsolutePath() + " does not exist");
}
}
initLogServer();
// Lucene
if (update == false && _wgaConfiguration.getLuceneManagerConfiguration().isEnabled()) {
try {
this.luceneManager = LuceneManager.retrieve(this, _wgaConfiguration.getLuceneManagerConfiguration());
log.debug("Lucene option 'maxBooleanClauseCount' set to '" + this.luceneManager.getBooleanQueryMaxClauseCount() + "'.");
log.debug("Lucene option 'maxDocsPerDBSession' set to '" + this.luceneManager.getMaxDocsPerDBSession() + "'.");
log.info("Lucene fulltext index enabled using index directory " + this.luceneManager.getIndexDirectory().getAbsolutePath());
}
catch (Exception e) {
log.error("Unable to initialize Lucene fulltext index: " + e.getClass().getName() + " - ", e);
}
}
// Personalisation
userAgentVerifier = new UserAgentVerifier(_wgaConfiguration.getPersonalisationConfiguration(), this);
// Design
DesignConfiguration designConfig = _wgaConfiguration.getDesignConfiguration();
designFileValidator = new DesignFileValidator(designConfig, this);
if (designConfig.getDefaultEncoding() == null) {
designConfig.setDefaultEncoding(DEFAULT_FILE_ENCODING);
getLog().info("No default design file encoding configured. Using '" + DEFAULT_FILE_ENCODING + "'.");
}
if (designFileCache == null) {
designFileCache = CacheFactory.createCache(CACHENAME_DESIGNFILES, _wgaConfiguration.getDesignConfiguration().getDesignFileCacheSize(), null);
}
// Custom core listeners - Get names here, instantiate later when
// library loader is inited
if (update == false) {
customCoreListenerClassnames = new HashSet(_wgaConfiguration.getCoreEventListeners());
}
_globalDbOptions = _wgaConfiguration.getGlobalDatabaseOptions();
_globalPublisherOptions = _wgaConfiguration.getGlobalPublisherOptions();
// init mail configuration
_mailConfig = WGAMailConfiguration.create(_wgaConfiguration.getMailConfiguration());
}
private void initLogServer() {
/* Currently deactivated since we have no remote applog viewer right now
try {
if(_logServer == null || !_logServer.isActive()) {
_logServer = new LogServer(this);
_logServer.start();
}
}
catch (Exception e) {
getLog().error("Error initializing remote applog server", e);
}*/
}
private void setLastCharacterEncoding(String characterEncoding) {
Preferences prefs = Preferences.userNodeForPackage(this.getClass());
prefs.put("LastCharacterEncoding", characterEncoding);
prefs.putLong("CharacterEncodingModified", System.currentTimeMillis());
}
private String getLastCharacterEncoding() {
Preferences prefs = Preferences.userNodeForPackage(this.getClass());
return prefs.get("LastCharacterEncoding", null);
}
public long getCharacterEncodingLastModified() {
Preferences prefs = Preferences.userNodeForPackage(this.getClass());
return prefs.getLong("CharacterEncodingModified", System.currentTimeMillis());
}
private void setLastDesignEncoding(String dbkey, String encoding) {
try {
Preferences prefs = Preferences.userNodeForPackage(this.getClass());
prefs.put(createPrefKeyDesignEncoding(dbkey), encoding);
prefs.putLong(createPrefKeyDesignEncodingLastModified(dbkey), System.currentTimeMillis());
} catch (Exception e) {
log.error("Unable to set lastDesignEncoding preferences.", e);
}
}
private String createPrefKeyDesignEncoding(String dbkey) throws NoSuchAlgorithmException {
return "LastDesignEncoding_" + WGUtils.hashPassword(dbkey.toLowerCase());
}
private String createPrefKeyDesignEncodingLastModified(String dbkey) throws NoSuchAlgorithmException {
return "DesignEncodingModified_" + WGUtils.hashPassword(dbkey.toLowerCase());
}
private String getLastDesignEncoding(String dbkey) {
Preferences prefs = Preferences.userNodeForPackage(this.getClass());
try {
return prefs.get(createPrefKeyDesignEncoding(dbkey), null);
}
catch (Exception e) {
log.error("Unable to retrieve preferences for 'LastDesignEncoding'", e);
return null;
}
}
public long getDesignEncodingLastModified(String dbkey) {
Preferences prefs = Preferences.userNodeForPackage(this.getClass());
try {
return prefs.getLong(createPrefKeyDesignEncodingLastModified(dbkey), System.currentTimeMillis());
}
catch (Exception e) {
log.error("Unable to retrieve preferences for 'DesignEncodingModified'", e);
return System.currentTimeMillis();
}
}
private void initReadMappings() {
//Element mappingsRoot = (Element) this.configDocument.getRootElement().selectSingleNode("mappings");
// get mapping class loader
buildLibraryLoaders();
// Default media mappings
this.systemMediaKeys.put(ENCODER_HTML, new MediaKey(ENCODER_HTML, "text/html", false, false));
this.systemMediaKeys.put(ENCODER_XML, new MediaKey(ENCODER_XML, "text/xml", false, true));
this.systemMediaKeys.put("wml", new MediaKey("wml", "text/wml", false, false));
this.systemMediaKeys.put("pdf", new MediaKey("pdf", "application/pdf", true, true));
log.info("Registering defaultAnalyzer to '" + defaultAnalyzer.getClass().getName() + "'");
}
private void initReadFilterMappings() {
List<WGAFilterConfig> newFilterMappings = new LinkedList<WGAFilterConfig>();
// read filter mappings from registry
Iterator filters = getModuleRegistry().getModulesForType(FilterConfigModuleType.class).values().iterator();
while (filters.hasNext()) {
ModuleDefinition modDef = (ModuleDefinition) filters.next();
try {
modDef.testDependencies();
FilterMapping mapping = (FilterMapping) modDef.getProperties();
WGAFilterConfig config = WGAFilterConfig.createFromMapping(mapping);
if (config != null) {
log.info("Adding filter '" + config.getFilterName() + "'");
newFilterMappings.add(config);
}
}
catch (ModuleDependencyException e) {
log.warn("Filter " + modDef.getTitle(Locale.getDefault()) + " deactivated in current WGA runtime: " + e.getMessage());
}
}
// read filter mappings from config
Iterator<FilterMapping> mappings = _wgaConfiguration.getFilterMappings().iterator();
while (mappings.hasNext()) {
WGAFilterConfig config = WGAFilterConfig.createFromMapping(mappings.next());
if (config != null) {
log.info("Adding filter '" + config.getFilterName() + "'");
newFilterMappings.add(config);
}
}
this.filterMappings = newFilterMappings;
}
public void addAnalyzerMapping(String language, String analyzerClassName) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
log.info("Registering analyzer mapping from language code '" + language + "' to '" + analyzerClassName + "'");
Class analyzerClass = getLibraryLoader().loadClass(analyzerClassName);
Analyzer analyzer = (Analyzer) analyzerClass.newInstance();
analyzerMappings.put(language.toLowerCase(), analyzer);
}
public void addFileHandlerMapping(String extension, String handlerClassName) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
log.info("Registering filehandler for extension '" + extension + "' - '" + handlerClassName + "'.");
Class fileHandlerClass = getLibraryLoader().loadClass(handlerClassName);
FileHandler handler = (FileHandler) fileHandlerClass.newInstance();
fileHandlerMappings.put(extension.toLowerCase(), handler);
}
private boolean addElementMapping(String name, String theClass, boolean system) {
if (system) {
this.systemElements.put(name, theClass);
return true;
}
else if (systemElements.containsKey(name)) {
getLog().warn("Cannot add WebTML element '" + name + "' because the name is already used in WGA configuration");
return false;
}
else {
this.customElements.put(name, theClass);
return true;
}
}
private boolean addEncoderMapping(String name, String theClass, boolean system) {
try {
name = name.toLowerCase();
Class formatterClass = getLibraryLoader().loadClass(theClass);
Object instance = formatterClass.newInstance();
if (instance instanceof ObjectFormatter) {
if (system) {
_systemFormatters.put(name, formatterClass);
}
else {
if (_systemFormatters.containsKey(name)) {
log.warn("Cannot add encoding formatter '" + name + "' because the name is already used by a formatter in WGA configuration");
return false;
}
_customFormatters.put(name, formatterClass);
}
return true;
}
else {
log.error("Encoding formatter '" + theClass + "' does not implement interface " + ObjectFormatter.class.getName());
}
}
catch (InstantiationException e) {
log.error("Error instantiating encoding formatter '" + theClass + "':" + e.getMessage());
}
catch (IllegalAccessException e) {
log.error("Access error instantiating encoding formatter '" + theClass + "':" + e.getMessage());
}
catch (ClassNotFoundException e) {
log.error("Encoding formatter class '" + theClass + "' could not be found");
}
catch (NoClassDefFoundError e) {
log.error("Encoding formatter class '" + theClass + "' could not be loaded", e);
}
return false;
}
private void buildLibraryLoaders() {
// Build jars list
List<URL> jarsList = new ArrayList<URL>();
String libraries = _wgaConfiguration.getServerOptions().get(WGAConfiguration.SERVEROPTION_LIBRARIES);
if (libraries != null && !libraries.trim().equals("")) {
StringTokenizer tokens = new StringTokenizer(libraries, ";");
int idx = 0;
String token;
while (tokens.hasMoreTokens()) {
token = tokens.nextToken();
try {
File tokenFile = new File(token);
if (!tokenFile.exists()) {
tokenFile = new File(getConfigFile().getParent(), token);
}
if (tokenFile.exists()) {
token = tokenFile.toURL().toString();
}
if (!token.equals("")) {
jarsList.add(new URL(token));
log.info("Registering class library URL " + token);
idx++;
}
}
catch (MalformedURLException e) {
this.log.warn("Library entry is neither a valid URL nor an existing file: " + token, e);
}
}
}
// add all jars from <configdir>/libs
File baseLibDir = getBaseLibraryDir();
if (baseLibDir != null && baseLibDir.exists() && baseLibDir.canRead()) {
File[] additionalJarFiles = baseLibDir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".jar");
}
});
for (File jarFile : additionalJarFiles) {
try {
jarsList.add(jarFile.toURL());
log.info("Registering library '" + jarFile.getAbsolutePath() + "'.");
} catch (MalformedURLException e) {
this.log.warn("Registering library '" + jarFile.getAbsolutePath() + "' failed.", e);
}
}
}
try {
// add all jars from /WEB-INF/isolated
Iterator resourcePaths = _context.getResourcePaths("/WEB-INF/isolated").iterator();
while (resourcePaths.hasNext()) {
jarsList.add(_context.getResource((String) resourcePaths.next()));
}
// Build URL array from jars list
URL[] loaderURLs = new URL[jarsList.size()];
for (int idx = 0; idx < jarsList.size(); idx++) {
loaderURLs[idx] = jarsList.get(idx);
}
baseLibraryLoader = new IsolatedJARLoader(loaderURLs, getClass().getClassLoader());
getLog().info("Creating WGA java library loader");
libraryClassLoadingChain = new DynamicClassLoadingChain(baseLibraryLoader);
WGFactory.setImplementationLoader(libraryClassLoadingChain);
updateLibraryLoader();
}
catch (MalformedURLException e1) {
log.fatal("Unable to create library loader! TMLScript will not work!", e1);
}
}
public File getBaseLibraryDir() {
File dir = new File(getWgaDataDir(),"lib");
if (!dir.exists()) {
dir.mkdirs();
}
return dir;
}
private void initTimerTasks() {
// Timer for resetting ip blocking info every 30 minutes
this.timer = new Timer();
TimerTask task = new CleanupTask();
long delay = 1000 * 60;
this.timer.scheduleAtFixedRate(task, delay, delay);
// Timer task for config file update
task = new ConfigUpdateTask(this);
delay = 1000 * 5;
this.timer.scheduleAtFixedRate(task, delay, delay);
// Timer task for monitoring developer plugins
String devPluginsPath = System.getProperty(SYSPROPERTY_DEVELOPER_PLUGINS);
if (devPluginsPath != null) {
File devPluginsFolder = getWGAFile(devPluginsPath);
if (devPluginsFolder.exists() && devPluginsFolder.isDirectory()) {
task = new DevPluginsMonitoringTask(devPluginsFolder);
delay = 1000 * 10;
this.timer.scheduleAtFixedRate(task, delay, delay);
}
}
}
private boolean isDBAllowed(Class implClass, String dbKey) {
return true;
}
private boolean isPersonalisationDBAllowed(Class implClass, String domain) {
return true;
}
private boolean isAllowedDBImplForXMLPublisher(Class implClass) {
return true;
}
public boolean isLocalRequest(HttpServletRequest request) {
try {
// if servername is not loopback --> return false
if (!InetAddress.getByName(request.getServerName()).isLoopbackAddress()) {
return false;
}
}
catch (UnknownHostException e1) {
// might happen if localhost cannot be looked up
// additional check for sure
if (!request.getServerName().toLowerCase().equals("localhost")) {
return false;
}
}
try {
// if remote address is not loopback -> return false
if (!InetAddress.getByName(request.getRemoteAddr()).isLoopbackAddress()) {
return false;
}
}
catch (UnknownHostException e1) {
// unparsable remote address - should not happen
return false;
}
return true;
}
public boolean hasPublisherLicense() {
return true;
}
public boolean areElementsAllowed() {
return true;
}
public boolean isPersonalisationEnabled() {
return true;
}
public boolean hasBrowserInterfaceLicense() {
return true;
}
public void contextInitialized(ServletContextEvent arg0) {
try {
_context = arg0.getServletContext();
// General inits
this.instanceActiveSince = new Date();
arg0.getServletContext().setAttribute(ATTRIB_CORE, this);
WGFactory.setAuthModuleFactory(new WGAAuthModuleFactory(this));
WGFactory.setMimetypeDeterminationService(new WGAMimetypeDeterminationService());
// Create temp dir
File mainTempDir = new File(System.getProperty("java.io.tmpdir"));
this.wgaTempDir = new File(mainTempDir, ".wgatemp");
if (wgaTempDir.exists()) {
killTempDir(wgaTempDir);
}
wgaTempDir.mkdir();
WGFactory.setTempDir(wgaTempDir);
// Creating logger
this.log = Logger.getLogger("wga");
initLoggingFile();
String debug = System.getProperty(SYSPROPERTY_DEBUG);
if (debug != null) {
Logger logger = Logger.getLogger(debug);
logger.setLevel(Level.DEBUG);
}
// Try to retrieve build properties
_finalBuild = true;
_buildSignature = "NOSIGNATURE";
try {
InputStream buildPropIn = _context.getResourceAsStream("/WEB-INF/wgabuild.properties");
Properties props = new Properties();
props.load(buildPropIn);
if (props.containsKey("finalBuild")) {
_finalBuild = Boolean.valueOf(props.getProperty("finalBuild")).booleanValue();
}
if (props.containsKey("signature")) {
_buildSignature = props.getProperty("signature");
}
}
catch (RuntimeException e1) {
}
// Retrieving platform info
String endDate = (new SimpleDateFormat("yyyy")).format(new Date());
log.info(getReleaseString() + " (c)2001-" + endDate + " InnovationGate GmbH");
try {
this.servletPlatform = new Double(arg0.getServletContext().getMajorVersion() + "." + arg0.getServletContext().getMinorVersion()).doubleValue();
this.jspPlatform = new Double(javax.servlet.jsp.JspFactory.getDefaultFactory().getEngineInfo().getSpecificationVersion()).doubleValue();
log.info("On platform " + arg0.getServletContext().getServerInfo() + " (Servlet Engine " + this.servletPlatform + ", JSP Engine " + this.jspPlatform + ")");
}
catch (Exception ecx) {
log.warn("Unable to retrieve platform info. Assuming Servlet Engine 2.3, JSP Engine 1.2");
this.servletPlatform = 2.2;
this.jspPlatform = 1.1;
}
arg0.getServletContext().setAttribute(WGACore.ATTRIB_SERVLET_ENGINE, new Double(this.servletPlatform));
arg0.getServletContext().setAttribute(WGACore.ATTRIB_JSP_ENGINE, new Double(this.jspPlatform));
// Starting other non-servlet services
this.deployer = new WGPDeployer(this);
this.getServletContext().setAttribute(WGACore.ATTRIB_DEPLOYER, this.deployer);
if (this.eventManager == null) {
this.eventManager = new EventManager(this);
}
// Create the statistics object
_usageStatistics = new WGAUsageStatistics(this);
// Try to instantiate JmxManager. We must test if jmx classes are
// available
try {
Class.forName("java.lang.management.ManagementFactory");
_wgaMonitor = new JmxManager(new WGAInformation(this), new ObjectName("de.innovationgate.WGAMonitor:context=" + arg0.getServletContext().getServletContextName() + ",name=Information"));
if (!JmxManager.JMX_DISABLED) {
log.info("WGA JMX metrics enabled");
}
}
catch (UnsupportedOperationException e) {
log.info("WGA JMX metrics disabled because no JMX MBean server available");
}
catch (ClassNotFoundException e) {
log.warn("WGA JMX metrics are not enabled since the neccessary API is not available");
}
catch (Throwable e) {
log.warn("Error enabling WGA JMX metrics: " + e.getClass().getName() + " - " + e.getMessage());
}
// Test some neccessary running conditions for WGA
// We test for exploded WAR
if (getServletContext().getRealPath("/") == null) {
log.fatal("WGA is not deployed as exploded WGA archive which is absolutely mandatory! WebTML deploying and rendering will not work correctly.");
}
// Eventually overwrite wga configpath/datapath/permanent log sysvar with init parameter
String initConfigPath = getServletContext().getInitParameter(SYSPROPERTY_CONFIGPATH);
if (initConfigPath != null) {
log.info("Using WGA config path from servlet init parameter: " + initConfigPath);
System.setProperty(SYSPROPERTY_CONFIGPATH, initConfigPath);
}
String initDataPath = getServletContext().getInitParameter(SYSPROPERTY_DATAPATH);
if (initDataPath != null) {
log.info("Using WGA data path from servlet init parameter: " + initDataPath);
System.setProperty(SYSPROPERTY_DATAPATH, initDataPath);
}
String initPermLog = getServletContext().getInitParameter(SYSPROPERTY_LOGPATH);
if (initPermLog != null) {
log.info("Using WGA permanent log path from servlet init parameter: " + initPermLog);
System.setProperty(SYSPROPERTY_LOGPATH, initPermLog);
}
// Do startup
fireCoreEvent(new WGACoreEvent(WGACoreEvent.TYPE_PRE_STARTUP, null, this));
startup();
}
catch (Exception e) {
log.fatal("Fatal error initializing wga", e);
e.printStackTrace();
}
}
public ServletContext getServletContext() {
return _context;
}
public static String getReleaseString() {
StringBuffer output = new StringBuffer();
output.append(WGAVersion.WGAPUBLISHER_PRODUCT_NAME).append(" ");
output.append(WGAVersion.WGAPUBLISHER_MAJOR_VERSION).append(".").append(WGAVersion.WGAPUBLISHER_MINOR_VERSION);
if (WGAVersion.WGAPUBLISHER_MAINTENANCE_VERSION > 0) {
output.append(".").append(WGAVersion.WGAPUBLISHER_MAINTENANCE_VERSION);
}
if (WGAVersion.WGAPUBLISHER_MAINTENANCE_VERSION > 0) {
output.append(" Maintenance Release");
}
else {
output.append(" Release");
}
if (WGAVersion.WGAPUBLISHER_PATCH_VERSION > 0) {
output.append(" Patch " + WGAVersion.WGAPUBLISHER_PATCH_VERSION);
}
if (isFinalBuild()) {
output.append(" (Build ").append(WGAVersion.WGAPUBLISHER_BUILD_VERSION).append(")");
}
else {
output.append(" (Interim version ").append(WGACore.getBuildSignature()).append(" of build ").append(WGAVersion.WGAPUBLISHER_BUILD_VERSION).append(")");
}
return output.toString();
}
public static String getPlatformString() {
StringBuffer output = new StringBuffer();
output.append(WGAVersion.WGAPUBLISHER_MAJOR_VERSION).append(".").append(WGAVersion.WGAPUBLISHER_MINOR_VERSION).append(" ");
output.append(WGAVersion.WGAPUBLISHER_PLATFORM_NAME);
return output.toString();
}
// Platform info
private double servletPlatform;
private double jspPlatform;
private ApplogAppender transientLogAppender = null;
private File loggingDir = null;
private AsyncAppender baseAppender = null;
public void initLoggingFile() {
// Base appender
if (this.baseAppender == null) {
this.baseAppender = new AsyncAppender();
this.baseAppender.setBufferSize(1000);
this.baseAppender.setBlocking(true);
this.log.addAppender(this.baseAppender);
}
// Transient log
if (this.transientLogAppender != null) {
this.baseAppender.removeAppender(this.transientLogAppender);
}
if (this.loggingDir != null && this.loggingDir.exists()) {
WGUtils.delTree(loggingDir);
}
this.loggingDir = new File(getWgaTempDir(), "applog");
this.transientLogAppender = new ApplogAppender(loggingDir.getAbsolutePath(), "wga-", ".log");
transientLogAppender.setName("wga.transientLog");
transientLogAppender.setAppend(true);
transientLogAppender.setEncoding("UTF-8");
transientLogAppender.setLayout(LAYOUT_APPLOG);
transientLogAppender.setMaxFileSize(1024 * 1024 * 10);
transientLogAppender.setFilesToKeep(10);
this.baseAppender.addAppender(transientLogAppender);
// Permanent log
String permanentLogPath = System.getProperty(SYSPROPERTY_LOGPATH);
if (permanentLogPath != null) {
File logPathFile = new File(permanentLogPath);
if (!logPathFile.exists() || !logPathFile.isDirectory()) {
log.error("Unable to use path for permanent log '" + permanentLogPath + "' because it either does not exist or is no directory.");
}
else {
log.info("Permanent application log stored in directory " + permanentLogPath);
DatedFileAppender permanentFileAppender = new DatedFileAppender(permanentLogPath, "wga-", ".log");
permanentFileAppender.setName("wga.permanentLog");
permanentFileAppender.setAppend(true);
permanentFileAppender.setEncoding("UTF-8");
permanentFileAppender.setLayout(LAYOUT_APPLOG);
this.baseAppender.addAppender(permanentFileAppender);
}
}
}
/**
* @return
*/
public File getWgaTempDir() {
return wgaTempDir;
}
/*
* (Kein Javadoc)
*
* @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
*/
public void contextDestroyed(ServletContextEvent arg0) {
try {
shutdown();
if (_wgaMonitor != null) {
_wgaMonitor.unregister();
}
WGFactory.getInstance().shutdown();
}
catch (Throwable t) {
log.error("Error shutting down WGA", t);
}
finally {
if (log != null) {
log.removeAllAppenders();
}
if (transientLogAppender != null) {
transientLogAppender.close();
}
if (wgaTempDir != null) {
killTempDir(wgaTempDir);
wgaTempDir = null;
}
// B000048C2 - cleanup temp. plugin resources
if (pluginSet != null) {
pluginSet.clearTempResources();
pluginSet = null;
}
}
}
public void shutdown() {
log.info(WGAVersion.WGAPUBLISHER_PRODUCT_NAME + " starting shutdown...");
fireCoreEvent(new WGACoreEvent(WGACoreEvent.TYPE_PRE_SHUTDOWN, null, this));
WGPDispatcher dispatcher = getDispatcher();
if (dispatcher != null) {
dispatcher.setServePages(false);
}
// Kill all timer tasks
try {
_quartzScheduler.shutdown(true);
}
catch (SchedulerException e) {
getLog().error("Exception shutting down WGA scheduler", e);
}
_quartzScheduler = null;
if (this.timer != null) {
this.timer.cancel();
this.timer = null;
}
// Cleanup lucene manager
if (luceneManager != null) {
luceneManager.destroy();
luceneManager = null;
}
if (_externalFileMaintenanceTask != null) {
_externalFileMaintenanceTask.stop();
_externalFileMaintenanceTask = null;
}
// fire pre disconnect event
fireCoreEvent(new WGACoreEvent(WGACoreEvent.TYPE_SHUTDOWN_PRE_DISCONNECT, null, this));
// Close content databases
Iterator<String> dbs = new HashSet<String>(this.contentdbs.keySet()).iterator();
while (dbs.hasNext()) {
removeContentDB(dbs.next());
}
// Close personalisation databases
dbs = new HashSet<String>(this.personalisationdbs.keySet()).iterator();
while (dbs.hasNext()) {
removePersonalisationDB(dbs.next());
}
// Close domains (especially their auth modules)
closeDomainConfigs(this.domainConfigs);
unDeployErrorPage();
WGHierarchicalDatabase.removeCoreListener(_hdbCoreListener);
// fire post disconnect event
fireCoreEvent(new WGACoreEvent(WGACoreEvent.TYPE_SHUTDOWN_POST_DISCONNECT, null, this));
// Close access logger
if (_accessLogger != null) {
_accessLogger.close();
}
// Cleanup deployer
deployer.shutdown();
// Cleanup statistics
if (_usageStatistics != null) {
_usageStatistics.dispose();
_usageStatistics = null;
}
// Remove all core listeners
eventListeners.clear();
// Close expression engines and WGA classpath
ExpressionEngineFactory.closeEngines();
libraryClassLoadingChain = null;
// Clear and close caches
WGFactory.getAuthModuleFactory().clearCache();
try {
designFileCache.destroy();
designFileCache = null;
}
catch (CacheException e) {
log.error("Exception closing design file cache", e);
}
try {
_calledSequenceIds.destroy();
_calledSequenceIds = null;
}
catch (CacheException e) {
log.error("Exception closing action sequence id cache", e);
}
// Close logserver
if (_logServer != null) {
try {
_logServer.shutdown();
}
catch (IOException e) {
getLog().error("Exception shutting down WGA Remote Log Server", e);
}
_logServer = null;
}
fireCoreEvent(new WGACoreEvent(WGACoreEvent.TYPE_POST_SHUTDOWN, null, this));
log.info(WGAVersion.WGAPUBLISHER_PRODUCT_NAME + " finished shutdown");
}
// Application attributes set by this program
public static final String ATTRIB_CORE = "Core";
public static final String ATTRIB_DISPATCHER = "Dispatcher";
public static final String ATTRIB_DEPLOYER = "Deployer";
public static final String ATTRIB_MAINCONTEXT = "TMLContext";
public static final String ATTRIB_CONTENTDBS = "Databases";
public static final String ATTRIB_WGPPATH = "WGPPath";
public static final String ATTRIB_PROFILE = "Profile:";
public static final String ATTRIB_SERVLET_ENGINE = "ServletEngine";
public static final String ATTRIB_JSP_ENGINE = "JspEngine";
public static final String ATTRIB_TAGIDS = "TagIds";
public static final String ATTRIB_TMLCONTEXTS = "TagContexts";
public static final String ATTRIB_PROFILING_ENABLED = "ProfilingEnabled";
public static final String ATTRIB_PROFILING_FILE = "ProfilingFile";
public static final String ATTRIB_REQUESTURL = "RequestURL";
public static final String ATTRIB_MEDIAKEY = "MediaKey";
public static final String ATTRIB_MIMETYPE = "MimeType";
public static final String ATTRIB_INITIALIZING_ENABLED = "InitializingEnabled";
public static final String ATTRIB_INITIALIZING_ROOT = "InitializingRoot";
public static final String ATTRIB_BROWSERINTERFACE = "BrowserInterface";
public static final String ATTRIB_NO_CONTENT_NOTIFCATION_URL = "de.innovationgate.wgpublisher.NoContentNotificationURL";
public static final String ATTRIB_VIRTUAL_CONTENT_URL = "de.innovationgate.wgpublisher.VirtualContentURL";
public static final String ATTRIB_EXCEPTION = "Exception";
public static final String ATTRIB_WGAERROR = "WGAError";
public static final String ATTRIB_OUTER_DESIGN = "OuterDesign";
public static final String ATTRIB_ROOT_TAG = "RootTag";
public static final String ATTRIB_LOGINERROR = "LoginError";
public static final String ATTRIB_META_MAPPINGS = "$MetaMappings";
public static final String ATTRIB_ITEM_MAPPINGS = "$ItemMappings";
public static final String ATTRIB_SERVLETRESPONSE = "OutputStream";
public static final String ATTRIB_ACTIONKEYNR = "ActionKeyNr";
public static final String ATTRIB_REDIRECT = "Redirect";
public static final String ATTRIB_REQUESTTIME = "RequestTime";
public static final String SESSION_ACTIONS = "Actions";
public static final String SESSION_ACTION_SEQUENCE = "ActionSequence";
public static final String SESSION_ADMINNAME = "AdminName";
public static final String SESSION_ADMINPASSWORD = "AdminPassword";
public static final String ATTRIB_TMLFORM = "TMLForm";
public static final String ATTRIB_LASTFORM = "LastForm";
/**
* Request Variable. When set to true forces WGA to perform a regular login
* and ignore other authentication information (like certificate, request user)
*/
public static final String ATTRIB_FORCEREGULARLOGIN = "ForceRegularLogin";
public static final String ATTRIB_REQUESTPATH = "RequestPath";
// Database attributes set by this program
public static final String DBATTRIB_DBKEY = "DBURLPath";
public static final String DBATTRIB_EXPRESSION_DEFAULT = "ExpressionDefault";
public static final String DBATTRIB_QUERY_DEFAULT = "QueryDefault";
public static final String DBATTRIB_DEFAULT_MEDIAKEY = "DefaultMediaKey";
public static final String DBATTRIB_ALLOW_BROWSING = "AllowBrowsing";
public static final String DBATTRIB_BROWSING_SECURITY = PublisherOption.OPTION_BROWSING_SECURITY;
public static final String DBATTRIB_STARTPAGE = "StartPage";
/**
* Boolean publisher option that identifies a database as authoring application
* WGA will restrict access to this database to a configured port or disable it et al
* if authoring is disabled by configuration.
*/
public static final String DBATTRIB_AUTHORING_APP = "AuthoringApp";
/**
* Boolean publisher option that identifies a database as admininstrative application
* WGA will restrict access to this database to a configured port and will not allow access
* if someone is not logged in as OpenWGA admin
*/
public static final String DBATTRIB_ADMIN_APP = "AdminApp";
public static final String DBATTRIB_MAXQUERYRESULTS = "MaxQueryResults";
public static final String DBATTRIB_DOMAIN = "Domain";
public static final String DBATTRIB_STORED_QUERIES = "StoredQueries";
public static final String DBATTRIB_META_MAPPINGS = "MetaMappings";
public static final String DBATTRIB_ITEM_MAPPINGS = "ItemMappings";
public static final String DBATTRIB_PLUGIN_SHORTCUTS = "PluginShortcuts";
public static final String DBATTRIB_HOME_PAGE = "HomePage";
public static final String DBATTRIB_LOGIN_PAGE = "LoginPage";
public static final String DBATTRIB_PERSMODE = "PersMode";
public static final String DBATTRIB_PERSSTATMODE = "PersStatMode";
public static final String DBATTRIB_FILEEXPIRATION_MINUTES = "FileExpirationMinutes";
public static final String DBATTRIB_FILECACHE = "FileCache";
public static final String DBATTRIB_FILECACHE_THRESHOLD = "FileCacheThreshold";
public static final String ATTRIB_BI_COLLECTIONS_SHOW_RELEASED_ONLY = "BICollectionsShowReleasedOnly";
/**
* Specifies the maximum number of entries in database file cache
*/
public static final String DBATTRIB_FILECACHE_ENTRIES = "FileCacheEntries";
public static final String DBATTRIB_VARPROVISIONING = "VarProvisioning";
public static final String DBATTRIB_TITLEPATHURL = "TitlePathURL";
public static final String DBATTRIB_TITLEPATHURL_CONTENTINDEXING = "TitlePathURL.ContentIndexing";
public static final String DBATTRIB_TITLEPATHURL_MIXEDLANGUAGES = "TitlePathURL.MixedLanguages";
public static final String DBATTRIB_TITLEPATHMANAGER = "TitlePathManager";
public static final String DBATTRIB_WEBTMLCACHE_SERVESTALEDATA = "WebTMLCache.ServeStaleData";
public static final String DBATTRIB_DEFAULT_ITEM_ENCODING = "DefaultItemEncoding";
public static final String DBATTRIB_USERCLASSES = "UserClasses";
public static final String DBATTRIB_RESOURCEBUNDLE_MANAGER = "ResourceBundleManager";
public static final String DBATTRIB_HTTPLOGIN = "HttpLogin";
public static final String DBATTRIB_LUCENE_CONFIG = "LuceneConfig";
// contains a list of IPv4Restrictions for a db
public static final String DBATTRIB_CLIENTRESTRICTIONS = "ClientRestrictions";
/**
* Boolean Attrib determines if the database is allowed to use remote docs
*/
public static final String DBATTRIB_USEREMOTECS = "UseRemoteContentStores";
/**
* Attribute to determine the language behaviour for a database, influencing
* the way the preferred language is determined
*/
public static final String DBATTRIB_LANGUAGEBEHAVIOUR = "LanguageBehaviour";
/**
* Boolean attrib determines if contents from this db may be used for remote
* docs
*/
public static final String DBATTRIB_ISREMOTECS = "IsRemoteContentStore";
// System properties
/**
* Directory from where to load wga configuration, defaults to the user's home directory. Many other locations are used relative to this path by default.
*/
public static final String SYSPROPERTY_CONFIGPATH = "de.innovationgate.wga.configpath";
/**
* Directory where WGA can store management data, defaults to CONFIPATH/wgadata
*/
public static final String SYSPROPERTY_DATAPATH = "de.innovationgate.wga.datapath";
/**
* Name of the WGA configuration file, defaults to wga.xml
*/
public static final String SYSPROPERTY_CONFIGFILE = "de.innovationgate.wga.configfile";
/**
* Can be used to set one log4j logging path to DEBUG level
*/
/**
* Can be used to set one log4j logging path to DEBUG level
*/
public static final String SYSPROPERTY_DEBUG = "de.innovationgate.wga.debug";
private static final String OLD_CONFIGFILE_NAME = "wga.xml";
private static final String CONFIGFILE_NAME = "wgaconfig.xml";
public static final java.text.DateFormat DATEFORMAT_GMT = new java.text.SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", new Locale("en", "US"));
Logger log = null;
private Date instanceActiveSince;
// domain configurations mapped by domainname
private Map<String, DomainConfiguration> domainConfigs;
private org.quartz.Scheduler _quartzScheduler;
private ArrayList<Object> customCoreListeners;
private SystemContainerManager _systemContainerManager;
private File _wgaDataDir;
private WGAConfiguration _wgaConfiguration;
private WGADesignManager _designManager;
private ModuleRegistry _moduleRegistry = null;
private WGALoggerWrapper _accessLogger;
private WGHierarchicalDatabaseCoreListener _hdbCoreListener;
private ExternalFileServingMaintenanceTask _externalFileMaintenanceTask;
public ModuleRegistry getModuleRegistry() {
return _moduleRegistry;
}
private static final String SYSPROPERTY_QUARTZ_THREADCOUNT = "de.innovationgate.wga.quartz.threadcount";
private static final String SYSPROPERTY_QUARTZ_THREADPRIORITY = "de.innovationgate.wga.quartz.threadpriority";
private static final String DEFAULT_CONFIG_DIR = "WGA";
public void startup() throws ServletException {
try {
this.log.info("Starting up wga service");
// prepare HDB
TMLScriptHDBListenerFactory listenerFactory = new TMLScriptHDBListenerFactory(this);
WGHierarchicalDatabase.setDefaultListenerFactory(listenerFactory);
WGHierarchicalDatabase.setDefaultStartupImpl(null);
_hdbCoreListener = new WGHierarchicalDatabaseCoreListener() {
public void databaseCreated(WGHierarchicalDatabase hdb) {
// Eventually load and initialize model
WGDatabase db = hdb.getWrappedDB();
try {
HDBModel.createModelObject(WGACore.this, db);
}
catch (Exception e) {
WGACore.this.log.error("Error initializing HDB model for database " + db.getDbReference(), e);
}
}
public void databaseRemoved(WGHierarchicalDatabase hdb) {
}
};
WGHierarchicalDatabase.addCoreListener(_hdbCoreListener);
String configFilePath = retrieveConfigPath();
// init DES-Encrypter
File desKeyFile = new File(configFilePath, "des.key");
desEncrypter = new DESEncrypter();
try {
try {
desEncrypter.init(desKeyFile);
log.info("DESEncrypter initialized using keyfile '" + desKeyFile.getPath() + "'.");
}
catch (DESEncrypter.PersistentKeyException e) {
log.warn(
"Unable to create or restore encryption key - generating temporary key. Session replication will not work with this key. Ensure the application server has read/write access to '"
+ desKeyFile.getPath() + "'.", e);
// init with temp key
desEncrypter.init();
log.info("DESEncrypter initialized with temporary key.");
}
}
catch (GeneralSecurityException e) {
// VM does not support 'des' algorithm - should not happen in
// wga supported VMs
log.error("Unable to create DESEncrypter.", e);
throw new ServletException("wga publisher initialization failure");
}
// get config xml document
boolean configMigrated = false;
this.configFile = retrieveConfigFile();
if (!configFile.exists()) {
// no new style wga configuration - check if we have to migrate an old one
File oldConfigFile = retrieveOldConfigFile();
if (oldConfigFile.exists()) {
migrateWGAConfiguration(oldConfigFile, configFile);
configMigrated = true;
} else {
// no previous old style config - create default config
createDefaultWGAConfiguration(configFile);
}
}
log.info("Using config file: " + configFile.getAbsolutePath());
this.configFileLastModified = this.configFile.lastModified();
parseConfigFile();
// Basic initializations
initQuartz();
deployer.startup();
_calledSequenceIds = CacheFactory.createCache("WGACore_calledSequenceIds", 10000, null);
String dataPath = System.getProperty(SYSPROPERTY_DATAPATH);
if (dataPath != null) {
_wgaDataDir = new File(dataPath);
}
else {
_wgaDataDir = new File(configFile.getParent(), "wgadata");
}
if (!_wgaDataDir.exists()) {
if (!_wgaDataDir.mkdir()) {
log.error("Unable to create WGA data directory '" + _wgaDataDir.getPath() + "'. Some WGA functionalities that rely on this will not work!");
_wgaDataDir = null;
}
}
else if (!_wgaDataDir.isDirectory()) {
log.error("Unable to create WGA data directory '" + _wgaDataDir.getPath() + "' because some other file uses the same name. Some WGA functionalities that rely on this will not work!");
_wgaDataDir = null;
}
String hsqlRoot = System.getProperty(de.innovationgate.webgate.api.hsql.WGDatabaseImpl.SYSPROPERTY_HSQL_ROOT);
if (WGUtils.isEmpty(hsqlRoot)) {
log.info("Setting root directory for embedded HSQLDB databases to config dir: " + configFile.getParentFile().getAbsolutePath());
System.setProperty(de.innovationgate.webgate.api.hsql.WGDatabaseImpl.SYSPROPERTY_HSQL_ROOT, configFile.getParentFile().getAbsolutePath());
}
else {
log.info("Root directory for embedded HSQLDB databases is: " + hsqlRoot);
}
String authFileRoot = System.getProperty(FileAuthenticationModule.SYSPROPERTY_AUTH_FOLDER);
if (WGUtils.isEmpty(authFileRoot)) {
log.info("Setting root directory for XML authentication files to config dir: " + configFile.getParentFile().getAbsolutePath());
System.setProperty(FileAuthenticationModule.SYSPROPERTY_AUTH_FOLDER, configFile.getParentFile().getAbsolutePath());
}
else {
log.info("Root directory for XML authentication files is: " + authFileRoot);
}
// retrieve general configuration
logCategoryInfo("General Configuration", 1);
initReadGeneralConfig(false);
// Initialize system container manager
_systemContainerManager = new SystemContainerManager(this);
// Retrieve media key and element mappings
logCategoryInfo("Mappings", 1);
initReadMappings();
// Create expression engines
ExpressionEngineFactory.createEngines();
// Initialize custom core listeners
initCustomCoreListeners();
// Read domain configurations
logCategoryInfo("Domains", 1);
Map<String, DomainConfiguration> newDomainConfigs = initReadDomains();
deployErrorPage();
// Init scheduler before db connection, so system containers in dbs can add jobs
_scheduler = new Scheduler(this);
// fire pre connect event
fireCoreEvent(new WGACoreEvent(WGACoreEvent.TYPE_STARTUP_PRE_CONNECT, null, this));
// connect plugins
logCategoryInfo("Plugins", 1);
updatePlugins(newDomainConfigs);
// Init module registry
logCategoryInfo("Modules", 1);
initModuleRegistry();
// Some tasks that adapt options in registry to those configured in the WGA configuration
adaptConfigurationToRegistry(configMigrated);
// Init filter mappings (which may be feeded from registry)
logCategoryInfo("Filter mappings", 1);
initReadFilterMappings();
// Init access logger - Must be after modreg so JDBC drivers from mod dependencies are already loaded
initAccessLogger();
// Startup domain configurations (must be after plugin connection so that domains can use plugin-provided functionalities)
logCategoryInfo("Domain authentications", 1);
initStartupDomains(newDomainConfigs);
// Init design manager
logCategoryInfo("Design Sources", 1);
_designManager = new WGADesignManager(this, _wgaConfiguration.getDesignConfiguration().getDesignSources());
// Init mail service
WGFactory.setMailService(new WGAMailService(this));
// open database servers
logCategoryInfo("Database servers", 1);
updateDatabaseServers();
// open content databases
logCategoryInfo("Web applications and data sources", 1);
Class defaultWorkflowEngine = WGFactory.getDefaultWorkflowEngine();
ModuleDefinition wfDef = getModuleRegistry().getModuleDefinition(WorkflowEngineModuleType.class, defaultWorkflowEngine);
if (wfDef != null) {
getLog().info("Default workflow engine is: " + wfDef.getTitle(Locale.ENGLISH));
}
else {
getLog().info("Default workflow engine is: " + defaultWorkflowEngine.getName() + " (custom unregistered engine)");
}
updateContentDBs(false);
// open personalisation databases
logCategoryInfo("Domain Personalisation Databases", 1);
updatePersonalisationDBs();
// fire post connect event
fireCoreEvent(new WGACoreEvent(WGACoreEvent.TYPE_STARTUP_POST_CONNECT, null, this));
// Declare timer tasks
initTimerTasks();
// Load scheduler jobs after db connection, so they can refer the connected dbs
logCategoryInfo("Scheduler", 1);
updateScheduler();
// Init shares
logCategoryInfo("Shares", 1);
updateShares();
this.getServletContext().setAttribute(WGACore.ATTRIB_CONTENTDBS, this.contentdbs);
// init TestCore
initTestCore();
// notify LuceneManger
logCategoryInfo("Lucene Fulltext Index", 1);
if (luceneManager != null) {
luceneManager.startup();
}
initExternalFileServing();
// start external file serving maintenance
_externalFileMaintenanceTask = new ExternalFileServingMaintenanceTask(this);
_externalFileMaintenanceTask.start();
// Init finished
logCategoryInfo(WGAVersion.WGAPUBLISHER_PRODUCT_NAME + " ready", 1);
WGFactory.getInstance().closeSessions();
fireCoreEvent(new WGACoreEvent(WGACoreEvent.TYPE_ONLINE, null, this));
}
catch (Exception exc) {
log.fatal("Fatal error initializing WGA", exc);
throw new ServletException("Servlet initialization failure", exc);
}
catch (Error err) {
log.fatal("Fatal error initializing WGA", err);
throw new ServletException("Servlet initialization failure", err);
}
finally {
WGPDispatcher dispatcher = getDispatcher();
if (dispatcher != null) {
dispatcher.setServePages(true);
}
}
}
private void adaptConfigurationToRegistry(boolean configMigrated) throws Exception, FileNotFoundException {
boolean changed = false;
// When migrated: remove default options from config (must be here so complete registry is available)
if (configMigrated) {
logCategoryInfo("Removing default options from migrated WGA configuration", 1);
getWgaConfiguration().removeDefaultOptions(getModuleRegistry());
changed = true;
}
// Create mandatory server options with full registry
if (createMandatoryServerOptions()) {
getLog().info("Creating mandatory server options in WGA configuration");
changed = true;
}
if (changed == true) {
getLog().info("Saving automatic adaptions to the WGA configuration");
WGAConfiguration.write(getWgaConfiguration(), new FileOutputStream(configFile));
}
}
private boolean createMandatoryServerOptions() {
boolean somethingChanged = false;
Map<String,String> serverOptions = getWgaConfiguration().getServerOptions();
for (ModuleDefinition modDef : getModuleRegistry().getModulesForType(WGAServerOptionsModuleType.class).values()) {
for (OptionDefinition optDef : modDef.getOptionDefinitions().values()) {
if (!optDef.isOptional() && optDef.getDefaultValue() != null) {
if (!serverOptions.containsKey(optDef.getName())) {
serverOptions.put(optDef.getName(), optDef.getDefaultValue());
somethingChanged = true;
}
}
}
}
return somethingChanged;
}
public static String retrieveConfigPath() throws IOException {
String configFilePath = System.getProperty(WGACore.SYSPROPERTY_CONFIGPATH);
if (WGUtils.isEmpty(configFilePath)) {
String userHome = System.getProperty("user.home");
File defaultConfigDir = new File(userHome, DEFAULT_CONFIG_DIR);
if (!defaultConfigDir.exists()) {
if (!defaultConfigDir.mkdirs()) {
throw new IOException("Unable to create default config directory " + defaultConfigDir.getPath());
}
}
configFilePath = defaultConfigDir.getPath();
}
return configFilePath;
}
private void initAccessLogger() {
// Close old access logger if present
if (_accessLogger != null) {
_accessLogger.close();
_accessLogger = null;
}
if (_wgaConfiguration.getAccessLog() != null) {
logCategoryInfo("Access logger", 1);
try {
_accessLogger = new WGALoggerWrapper(_wgaConfiguration.getAccessLog(), this);
}
catch (Exception e) {
this.log.error("Exception instantiating access logger", e);
_accessLogger = null;
}
}
}
private void updateDatabaseServers() {
Map<String, WGDatabaseServer> newServers = new ConcurrentHashMap<String, WGDatabaseServer>();
// Add singleton servers
Iterator<ModuleDefinition> singletons = getModuleRegistry().getModulesForType(DatabaseServerModuleType.class).values().iterator();
while (singletons.hasNext()) {
ModuleDefinition serverDefinition = singletons.next();
DatabaseServerProperties properties = (DatabaseServerProperties) serverDefinition.getProperties();
if (properties == null) {
getLog().error("Database server type '" + serverDefinition.getTitle(Locale.getDefault()) + "' (" + serverDefinition.getImplementationClass().getName() + ") is invalid, misses neccessary properties definition");
}
else if (properties.isSingleton()) {
try {
serverDefinition.testDependencies();
WGDatabaseServer server = (WGDatabaseServer) getModuleRegistry().instantiate(serverDefinition);
server.init(WGAConfiguration.SINGLETON_SERVER_PREFIX + server.getClass().getName(), null, new HashMap<String,String>());
newServers.put(server.getUid(), server);
getLog().info("Registering database server '" + server.getTitle(Locale.getDefault()) + "' (Automatically created)");
}
catch (ModuleDependencyException e) {
getLog().error("Database server " + serverDefinition.getTitle(Locale.getDefault()) + " deactivated in current WGA runtime: " + e.getMessage());
}
catch (Exception e) {
getLog().error("Exception instantiating database server", e);
}
}
}
// Add servers from configuration
Iterator<DatabaseServer> servers = getWgaConfiguration().getDatabaseServers().iterator();
while (servers.hasNext()) {
DatabaseServer databaseServer = servers.next();
if (databaseServer.isEnabled()) {
try {
Class serverClass = getLibraryLoader().loadClass(databaseServer.getImplClassName());
WGDatabaseServer server = (WGDatabaseServer) getModuleRegistry().instantiate(serverClass);
server.init(databaseServer.getUid(), databaseServer.getTitle(), databaseServer.getOptions());
newServers.put(server.getUid(), server);
getLog().info("Registering database server '" + server.getTitle(Locale.getDefault()) + "'");
}
catch (Exception e) {
getLog().error("Exception instantiating database server", e);
}
}
}
_databaseServers = newServers;
}
private Map<String,WGDatabaseServer> _databaseServers = new ConcurrentHashMap<String, WGDatabaseServer>();
private List<HTMLHeadInclusion> _htmlHeadInclusions = new ArrayList<HTMLHeadInclusion>();
private void initModuleRegistry() {
// Initialize module registry and retrieve definitions
_moduleRegistry = new WGAModuleRegistry();
_moduleRegistry.setClassLoader(getLibraryLoader());
WGFactory.setModuleRegistry(_moduleRegistry);
_moduleRegistry.getContextObjects().put(WGACore.class, this);
updateModuleDefinitions(true);
PasswordOptionEncoder encoder;
String passwordEncoderKey = _wgaConfiguration.getPasswordEncoding();
try {
ModuleDefinition passwordEncoderModDef = _moduleRegistry.getModuleDefinitionByKey(PasswordEncodingType.class, passwordEncoderKey);
if (passwordEncoderModDef != null) {
Class passwordEncoderClass = passwordEncoderModDef.getImplementationClass();
encoder = (PasswordOptionEncoder) passwordEncoderClass.newInstance();
}
else {
getLog().error("Unknown password encoder key " + passwordEncoderKey);
getLog().error("Falling back to Base64 encoder for encoding new passwords");
encoder = new Base64();
}
}
catch (Exception e1) {
getLog().error("Exception creating password encoder " + passwordEncoderKey, e1);
getLog().error("Falling back to Base64 encoder for encoding new passwords");
encoder = new Base64();
}
_moduleRegistry.getContextObjects().put(PasswordEncodingType.class, encoder);
Map<ModuleDefinition,Exception> dependencyFailures = new HashMap<ModuleDefinition, Exception>();
Iterator<ModuleDefinition> serverMods = _moduleRegistry.getModulesForType(DatabaseServerModuleType.class).values().iterator();
if (serverMods.hasNext()) {
logCategoryInfo("Database server types available in this runtime", 2);
while (serverMods.hasNext()) {
ModuleDefinition moduleDefinition = serverMods.next();
try {
moduleDefinition.testDependencies();
DatabaseServerProperties props = (DatabaseServerProperties) moduleDefinition.getProperties();
if (props != null && props.isSingleton()) {
getLog().info("- " + moduleDefinition.getTitle(Locale.ENGLISH) + " (Automatic instance)");
}
else {
getLog().info("- " + moduleDefinition.getTitle(Locale.ENGLISH));
}
}
catch (Exception e) {
dependencyFailures.put(moduleDefinition, e);
}
}
}
Iterator<ModuleDefinition> dbMods = _moduleRegistry.getModulesForType(ContentStoreModuleType.class).values().iterator();
if (dbMods.hasNext()) {
logCategoryInfo("Content store types available in this runtime", 2);
while (dbMods.hasNext()) {
ModuleDefinition moduleDefinition = dbMods.next();
try {
moduleDefinition.testDependencies();
getLog().info("- " + moduleDefinition.getTitle(Locale.ENGLISH));
}
catch (Exception e) {
dependencyFailures.put(moduleDefinition, e);
}
}
}
Iterator<ModuleDefinition> customdbMods = _moduleRegistry.getModulesForType(ContentDatabaseModuleType.class).values().iterator();
if (customdbMods.hasNext()) {
logCategoryInfo("Other content database types available in this runtime", 2);
while (customdbMods.hasNext()) {
ModuleDefinition moduleDefinition = customdbMods.next();
try {
moduleDefinition.testDependencies();
getLog().info("- " + moduleDefinition.getTitle(Locale.ENGLISH));
}
catch (Exception e) {
dependencyFailures.put(moduleDefinition, e);
}
}
}
Iterator<ModuleDefinition> persdbMods = _moduleRegistry.getModulesForType(PersonalisationDatabaseModuleType.class).values().iterator();
if (persdbMods.hasNext()) {
logCategoryInfo("Personalisation database types available in this runtime", 2);
while (persdbMods.hasNext()) {
ModuleDefinition moduleDefinition = persdbMods.next();
try {
moduleDefinition.testDependencies();
getLog().info("- " + moduleDefinition.getTitle(Locale.ENGLISH));
}
catch (Exception e) {
dependencyFailures.put(moduleDefinition, e);
}
}
}
Iterator<ModuleDefinition> authMods = _moduleRegistry.getModulesForType(AuthenticationSourceModuleType.class).values().iterator();
if (authMods.hasNext()) {
logCategoryInfo("Authentication types available in this runtime", 2);
while (authMods.hasNext()) {
ModuleDefinition moduleDefinition = authMods.next();
try {
moduleDefinition.testDependencies();
getLog().info("- " + moduleDefinition.getTitle(Locale.ENGLISH));
}
catch (Exception e) {
dependencyFailures.put(moduleDefinition, e);
}
}
}
Iterator<ModuleDefinition> wfMods = _moduleRegistry.getModulesForType(WorkflowEngineModuleType.class).values().iterator();
if (wfMods.hasNext()) {
logCategoryInfo("Workflow engine types available in this runtime", 2);
while (wfMods.hasNext()) {
ModuleDefinition moduleDefinition = wfMods.next();
try {
moduleDefinition.testDependencies();
getLog().info("- " + moduleDefinition.getTitle(Locale.ENGLISH));
}
catch (Exception e) {
dependencyFailures.put(moduleDefinition, e);
}
}
}
Iterator<ModuleDefinition> designMods = _moduleRegistry.getModulesForType(DesignSourceModuleType.class).values().iterator();
if (designMods.hasNext()) {
logCategoryInfo("Design source types available in this runtime", 2);
while (designMods.hasNext()) {
ModuleDefinition moduleDefinition = designMods.next();
try {
moduleDefinition.testDependencies();
DesignSourceProperties props = (DesignSourceProperties) moduleDefinition.getProperties();
if (props != null && props.isSingleton()) {
getLog().info("- " + moduleDefinition.getTitle(Locale.ENGLISH) + " (Automatic instance)");
}
else {
getLog().info("- " + moduleDefinition.getTitle(Locale.ENGLISH));
}
}
catch (Exception e) {
dependencyFailures.put(moduleDefinition, e);
}
}
}
Iterator<ModuleDefinition> contentShareMods = _moduleRegistry.getModulesForType(ShareModuleType.class).values().iterator();
if (contentShareMods.hasNext()) {
logCategoryInfo("Share types available in this runtime", 2);
while (contentShareMods.hasNext()) {
ModuleDefinition moduleDefinition = contentShareMods.next();
try {
moduleDefinition.testDependencies();
getLog().info("- " + moduleDefinition.getTitle(Locale.ENGLISH));
}
catch (Exception e) {
dependencyFailures.put(moduleDefinition, e);
}
}
}
Iterator<ModuleDefinition> taskMods = _moduleRegistry.getModulesForType(SchedulerTaskModuleType.class).values().iterator();
if (taskMods.hasNext()) {
logCategoryInfo("Scheduler tasks available in this runtime", 2);
while (taskMods.hasNext()) {
ModuleDefinition moduleDefinition = taskMods.next();
try {
moduleDefinition.testDependencies();
getLog().info("- " + moduleDefinition.getTitle(Locale.ENGLISH));
}
catch (Exception e) {
dependencyFailures.put(moduleDefinition, e);
}
}
}
Iterator<Map.Entry<ModuleDefinition,Exception>> failureMods = dependencyFailures.entrySet().iterator();
if (failureMods.hasNext()) {
logCategoryInfo("Modules not available to this runtime because of missing dependencies", 2);
while (failureMods.hasNext()) {
Map.Entry<ModuleDefinition,Exception> failure = failureMods.next();
try {
getLog().info("- " + failure.getKey().getTitle(Locale.ENGLISH) + ": " + failure.getValue().getMessage());
}
catch (Exception e) {
getLog().error("- " + failure.getKey().getImplementationClass() + ": Exception while logging dependency failure", e);
}
}
}
}
public void updateModuleDefinitions(boolean initialRegistration) {
// Search for new module definitions
try {
_moduleRegistry.searchModuleDefinitions();
}
catch (IOException e) {
getLog().error("Exception searching module definitions", e);
}
// Post processings
// Instantiate registered HTML head inclusions
List<HTMLHeadInclusion> htmlHeadInclusions = new ArrayList<HTMLHeadInclusion>();
for (ModuleDefinition def : _moduleRegistry.getModulesForType(HTMLHeadInclusionModuleType.class).values()) {
try {
HTMLHeadInclusion inc = (HTMLHeadInclusion) _moduleRegistry.instantiate(def);
htmlHeadInclusions.add(inc);
}
catch (Throwable e) {
getLog().error("Exception processing HTML head inclusion " + def.getTitle(Locale.getDefault()), e);
}
}
_htmlHeadInclusions = htmlHeadInclusions;
}
private void createDefaultWGAConfiguration(File file) throws Exception {
log.info("Creating default wga configuration in file '" + file.getAbsolutePath() + "'.");
WGAConfiguration defaultConfig = WGAConfiguration.createDefaultConfig();
WGAConfiguration.write(defaultConfig, new FileOutputStream(file));
}
private void migrateWGAConfiguration(File oldConfigFile, File newConfigFile) throws Exception {
MigrationResult migrationResult = WGAConfigurationMigrator.createFromWGAXML(new FileInputStream(oldConfigFile), oldConfigFile.getParentFile().getAbsolutePath());
Iterator<MigrationMessage> logEntries = migrationResult.getLog().iterator();
File migrationLogFile = new File(newConfigFile.getParentFile(), "migration.log");
BufferedWriter writer = new BufferedWriter(new FileWriter(migrationLogFile));
while (logEntries.hasNext()) {
MigrationMessage message = logEntries.next();
if (message.getLevel() == MigrationMessage.INFO) {
log.info(message.getMessage());
writer.write("INFO - " + message.getMessage() + "\n");
writer.write("\n");
} else if (message.getLevel() == MigrationMessage.WARNING) {
if (message.getThrowable() != null) {
log.warn(message.getMessage(), message.getThrowable());
writer.write("WARN - " + message.getMessage() + "\n");
message.getThrowable().printStackTrace(new PrintWriter(writer));
} else {
log.warn(message.getMessage());
writer.write("WARN - " + message.getMessage() + "\n");
writer.write("\n");
}
} else if (message.getLevel() == MigrationMessage.ERROR) {
if (message.getThrowable() != null) {
log.error(message.getMessage(), message.getThrowable());
writer.write("ERROR - " + message.getMessage() + "\n");
message.getThrowable().printStackTrace(new PrintWriter(writer));
writer.write("\n");
} else {
log.error(message.getMessage());
writer.write("ERROR - " + message.getMessage() + "\n");
}
}
}
writer.close();
try {
WGAConfiguration.write(migrationResult.getConfig(), new FileOutputStream(newConfigFile));
}
catch (Exception e) {
newConfigFile.delete();
throw e;
}
}
private void initCustomCoreListeners() {
// From configuration
customCoreListeners = new ArrayList<Object>();
Iterator classesIt = customCoreListenerClassnames.iterator();
while (classesIt.hasNext()) {
String clazzName = (String) classesIt.next();
try {
Class clazz = getLibraryLoader().loadClass(clazzName);
Object listenerObj = clazz.newInstance();
if (!(listenerObj instanceof WGACoreEventListener)) {
getLog().error("Event listener '" + clazzName + "' is no implementation of " + WGACoreEventListener.class.getName());
continue;
}
addEventListener((WGACoreEventListener) listenerObj);
customCoreListeners.add(listenerObj);
}
catch (ClassNotFoundException e) {
getLog().error("Cannot load event listener '" + clazzName + "' because class could not be found");
}
catch (InstantiationException e) {
getLog().error("Error instantiating event listener '" + clazzName + "'", e);
}
catch (IllegalAccessException e) {
getLog().error("Access error instantiating event listener '" + clazzName + "'", e);
}
}
}
private void initTestCore() {
// if not set yet create TestCore and disable
if (_testCore == null) {
boolean testsEnabled = Boolean.parseBoolean(System.getProperty(SYSPROPERTY_UNITTEST));
String logDir = System.getProperty(SYSPROPERTY_UNITTEST_LOGDIR, null);
if (logDir != null) {
_testCore = new TestCore(this, testsEnabled, logDir);
} else {
_testCore = new TestCore(this, testsEnabled);
}
}
}
private void initQuartz() {
try {
int threadCount = 5;
String threadCountConfig = System.getProperty(SYSPROPERTY_QUARTZ_THREADCOUNT);
if (threadCountConfig != null) {
try {
threadCount = Integer.parseInt(threadCountConfig);
}
catch (NumberFormatException e) {
getLog().error("Unable to parse " + SYSPROPERTY_QUARTZ_THREADCOUNT + " as integer. Using default of " + threadCount);
}
}
int threadPriority = Thread.MIN_PRIORITY;
String threadPrioConfig = System.getProperty(SYSPROPERTY_QUARTZ_THREADPRIORITY);
if (threadPrioConfig != null) {
try {
threadPriority = Integer.parseInt(threadPrioConfig);
}
catch (NumberFormatException e) {
getLog().error("Unable to parse " + SYSPROPERTY_QUARTZ_THREADPRIORITY + " as integer. Using default of " + threadPriority);
}
}
ThreadPool threadPool = new SimpleThreadPool(threadCount, threadPriority);
threadPool.initialize();
JobStore jobStore = new RAMJobStore();
DirectSchedulerFactory.getInstance().createScheduler(threadPool, jobStore);
_quartzScheduler = DirectSchedulerFactory.getInstance().getScheduler();
_quartzScheduler.start();
}
catch (SchedulerException e) {
getLog().fatal("Unable to start wga scheduler. Some background tasks may not run!", e);
}
}
private Map<String, DomainConfiguration> initReadDomains() {
// Map new configs
Map<String, DomainConfiguration> newDomainConfigs = new HashMap<String, DomainConfiguration>();
Iterator<Domain> domains = _wgaConfiguration.getDomains().iterator();
while (domains.hasNext()) {
Domain domain = domains.next();
DomainConfiguration domainConfig = new DomainConfiguration(domain);
// TODO this check should be done in configuration
if (domainConfig.getName().startsWith(PluginConfig.PLUGIN_DBKEY_PREFIX)) {
this.log.error("Domain name '" + domainConfig.getName() + "' invalid. The prefix '" + PluginConfig.PLUGIN_DBKEY_PREFIX + "' is reserved for WGA plugin domains.");
continue;
}
newDomainConfigs.put(domainConfig.getName(), domainConfig);
this.log.info("Reading configuration of domain '" + domainConfig.toString() + "'");
}
return newDomainConfigs;
}
private void initStartupDomains(Map<String, DomainConfiguration> newDomainConfigs) {
// Initialize new domain configurations (their auth modules, that is)
Iterator<DomainConfiguration> doms = newDomainConfigs.values().iterator();
while (doms.hasNext()) {
DomainConfiguration cfg = doms.next();
logCategoryInfo("Domain " + cfg.getName(), 2);
try {
cfg.init();
if (cfg.getAuthModule() != null) {
getLog().info("Uses: " + cfg.getAuthModule().getAuthenticationSource());
}
else {
getLog().info("Uses no authentication");
}
}
catch (Exception e) {
getLog().error("Exception initializing authentication for domain " + cfg.getName(), e);
}
}
// Replace old domain configs with new domain configs
Map<String, DomainConfiguration> oldDomainConfigs = this.domainConfigs;
this.domainConfigs = newDomainConfigs;
closeDomainConfigs(oldDomainConfigs);
}
private void closeDomainConfigs(Map<String, DomainConfiguration> oldDomainConfigs) {
if (oldDomainConfigs == null) {
return;
}
for (DomainConfiguration cfg : oldDomainConfigs.values()) {
try {
cfg.destroy();
}
catch (Throwable e) {
getLog().error("Exception closing domain " + cfg.getName(), e);
}
}
}
private void updateScheduler() {
try {
String loggingDirStr = _wgaConfiguration.getSchedulerConfiguration().getLoggingDir();
if (loggingDirStr != null) {
_scheduler.setLoggingDir(new File(loggingDirStr));
}
// Register all currently configured jobs
Iterator<de.innovationgate.wga.config.Job> jobs = _wgaConfiguration.getSchedulerConfiguration().getJobs().iterator();
List<String> currentJobs = new ArrayList<String>();
while (jobs.hasNext()) {
de.innovationgate.wga.config.Job job = jobs.next();
String jobName = job.getName();
try {
_scheduler.addJob(job);
currentJobs.add(jobName);
}
catch (ConfigurationException e) {
getLog().error("Configuration error initializing job '" + jobName + "': " + e.getMessage(), e);
}
}
// Remove all wgaconfig jobs, no more in configuration
List jobsToRemove = new ArrayList(_scheduler.getJobNames());
jobsToRemove.removeAll(currentJobs);
Iterator removeIt = jobsToRemove.iterator();
while (removeIt.hasNext()) {
String jobName = (String) removeIt.next();
Job job = _scheduler.getJob(jobName);
if (job != null && job.getOrigin() == Job.ORIGIN_WGACONFIG) {
_scheduler.removeJob(jobName);
}
}
}
catch (RuntimeException e) {
getLog().error("Failed to update WGA schedules.", e);
}
}
private void parseConfigFile() throws Exception {
try {
logCategoryInfo("Parsing WGA Configuration", 1);
_wgaConfiguration = WGAConfiguration.read(new FileInputStream(configFile));
List<ValidationError> errors = _wgaConfiguration.validate();
if (!errors.isEmpty()) {
log.error("WGA configuration contains validation errors:");
for (ValidationError error : errors) {
log.error("- " + error.getMessage());
}
}
} catch (ConfigValidationException e) {
log.fatal("WGA configuration integrity check fails:");
Iterator<ValidationError> errors = e.getValidationErrors().iterator();
while (errors.hasNext()) {
ValidationError error = errors.next();
log.fatal("- " + error.getMessage());
}
throw e;
}
}
/**
* retrieves the old wga config file "wga.xml"
* @return
*/
private File retrieveOldConfigFile() {
File configFile = null;
String configFilePath = System.getProperty(WGACore.SYSPROPERTY_CONFIGPATH);
if (configFilePath == null) {
configFilePath = System.getProperty("user.home");
}
return new File(configFilePath, WGACore.OLD_CONFIGFILE_NAME);
}
/**
* retrieve the new wga config file "wgaconfig.xml"
* @return
* @throws ServletException
*/
private File retrieveConfigFile() throws IOException {
return new File(retrieveConfigPath(), WGACore.CONFIGFILE_NAME);
}
// Maps of objects
private Map<String,WGDatabase> contentdbs = new ConcurrentHashMap<String, WGDatabase>();
private Map<String,WGDatabase> personalisationdbs = new ConcurrentHashMap<String,WGDatabase>();
private Map<String,MediaKey> systemMediaKeys = new ConcurrentHashMap<String, MediaKey>();
private Map<String, MediaKey> customMediaKeys = new ConcurrentHashMap<String, MediaKey>();
private Map<String, String> systemElements = new ConcurrentHashMap<String, String>();
private Map<String, String> customElements = new ConcurrentHashMap<String, String>();
private Set<LicenseBindingKey> authorLicenseBindings = Collections.synchronizedSet(new HashSet<LicenseBindingKey>());
private File configFile;
private long configFileLastModified;
//private Document configDocument;
private Timer timer;
private long numberOfAuthorLicenses = 0;
private WGAPluginSet pluginSet;
private TMLScriptGlobalRegistry _tmlscriptGlobalRegistry = new TMLScriptGlobalRegistry();
private int _status;
private WGAFilter _filter;
private String _errorPage;
public static final String DEFAULT_FILE_ENCODING = "ISO-8859-1";
public static final int DEFAULT_QUERY_MAXRESULTS = 500;
public static final String ATTRIB_BI_VERSION4 = "BrowserInterfaceVersion4";
public static final String ATTRIB_BI_VERSION3 = "BrowserInterfaceVersion3";
public static final String ATTRIB_BI_INCLUDE_BI3_SCRIPTS = "BrowserInterfaceIncludeBI3Scripts";
public static final java.text.DateFormat DATEFORMAT_LOCAL = new java.text.SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
public static final String ATTRIB_PORTLETKEYS = "PortletKeys";
public static final String SESSION_PORTLETMODES = "portletmodes";
public static final String DBATTRIB_SESSIONCOOKIEDOMAIN = "SessionCookieDomain";
public static final String ATTRIB_TMLDEBUG_TRACE_OPTIONS = "tmlDebugTraceOptions";
public static final String DBATTRIB_CSCONFIG = "CSConfig";
public static final String SESSION_FIREDPORTLETEVENTS = "firedPortletEvents";
public static final String DBATTRIB_PLUGIN_FILETIME = "PluginFileTime";
public static final String DBATTRIB_PLUGIN_VERSION = "PluginVersion";
public static final Object WGASERVICES_WSDL_URL = "wgaservices.wsdl";
public static final String ATTRIB_URLBUILDER = "URLBuilder";
public static final String DBATTRIB_TITLEPATHURL_SHORTCUTAREA = "TitlePathURL.ShortcutArea";
public static final String DBATTRIB_ALLOW_PUBLISHING = "AllowPublishing";
public static final String DBATTRIB_SHARE_ALLOWALLCHARS = "Share.AllowAllCharacters";
public static final String DBATTRIB_CREATE_NAME_URLS = "CreateNameURLs";
public static final String ATTRIB_AUTHORINGMODE = "AuthoringMode.";
public static final String DBATTRIB_PLUGIN_ID = "PluginID";
/**
* dummy dbkey for static tml requests
*/
public static final String STATICTML_DESIGNDBKEY = "de.innovationgate.wga.statictml.DesignDB";
public static final String DBATTRIB_HDBMODEL = "HDBModel";
private static final String ENCODER_NONE = "none";
public static final String DBATTRIB_ENABLE_ACCESSLOGGING = "EnableAccessLogging";
public static final String DBATTRIB_URLBUILDER = "URLBuilder";
public static final String DBATTRIB_SECURE_APP = "SecureApp";
public static final String DBATTRIB_LANGUAGEBEHAVIOUR_INSTANCE = "LanguageBehaviourInstance";
public static final String DBATTRIB_EXTERNAL_FILE_SERVING_ENABLED = "ExternalFileServingEnabled";
public static final String ATTRIB_VAR_PARAMETERS = "VarParameters";
// Server options
public WGPDispatcher getDispatcher() {
return (WGPDispatcher) _context.getAttribute(ATTRIB_DISPATCHER);
}
public Logger getLog() {
return log;
}
public Set<LicenseBindingKey> getAuthorLicenseBindings() {
return authorLicenseBindings;
}
/*
public Document getConfigDocument() {
return configDocument;
}*/
public Map<String, WGDatabase> getContentdbs() {
return contentdbs;
}
public Map<String, WGDatabase> getDesigndbs() {
Map<String, WGDatabase> mapDesigndbs = new HashMap<String, WGDatabase>();
Map<String, WGDatabase> mapContentdbs = this.getContentdbs();
Iterator<String> iter = mapContentdbs.keySet().iterator();
WGDatabase db = null;
while (iter.hasNext()) {
db = mapContentdbs.get(iter.next());
if (db.isDesignRole()) {
mapDesigndbs.put((String) db.getAttribute(WGACore.DBATTRIB_DBKEY), db);
}
}
if (mapDesigndbs != null) {
return mapDesigndbs;
}
else {
return null;
}
}
/**
* returns all designdbs of the given domain
*
* @param domain
* @return
*/
public Map<String, WGDatabase> getDesigndbs(String domain) {
Map<String, WGDatabase> designDBs = getDesigndbs();
Iterator<String> it = designDBs.keySet().iterator();
Map<String, WGDatabase> domainDesignDBs = new HashMap<String, WGDatabase>();
while (it.hasNext()) {
String currentDBKey = it.next();
WGDatabase db = designDBs.get(currentDBKey);
String currentDomain = (String) db.getAttribute(WGACore.DBATTRIB_DOMAIN);
if (domain.equals(currentDomain)) {
domainDesignDBs.put(currentDBKey, db);
}
}
return domainDesignDBs;
}
public String getDefaultMediaKey() {
return defaultMediaKey;
}
public WGPDeployer getDeployer() {
return deployer;
}
public Date getInstanceActiveSince() {
return instanceActiveSince;
}
public long getNumberOfAuthorLicenses() {
return numberOfAuthorLicenses;
}
public Map<String, WGDatabase> getPersonalisationdbs() {
return personalisationdbs;
}
public boolean isProfilingEnabled() {
return profilingEnabled;
}
public int getTmlBuffer() {
return tmlBuffer;
}
public String getTmlHeader() {
return tmlHeader;
}
public ObjectFormatter getEncodingFormatter(String encode, TMLContext context) throws FormattingException {
encode = encode.toLowerCase();
List<String> flagList = new ArrayList<String>();
Set<String> flags = new HashSet<String>();
// split up flags from encoder name
int pos = encode.indexOf(":");
if (pos != -1) {
String strFlags = encode.substring(pos + 1);
flagList = Arrays.asList(strFlags.split("\\|"));
flags.addAll(flagList);
encode = encode.substring(0, pos);
}
ObjectFormatter formatter = null;
if (encode.equalsIgnoreCase(ENCODER_HTML) || encode.equalsIgnoreCase(ENCODER_XML)) {
formatter = new EncodingFormatter(encode);
}
else if (encode.equalsIgnoreCase(ENCODER_RTF)) {
formatter = new RTFEncodingFormatter(flags);
}
else if (encode.equalsIgnoreCase(ENCODER_RTFSYSTEM)) {
flags.add(RTFEncodingFormatter.FLAG_ONLY_SYSTEM_MACROS);
formatter = new RTFEncodingFormatter(flags);
}
else if (encode.equalsIgnoreCase(ENCODER_CRLF)) {
formatter = new CRLFEncoder();
}
else if (encode.equalsIgnoreCase(ENCODER_PLAINTEXT)) {
formatter = new PlainTextFormatter();
}
else if (encode.equalsIgnoreCase(ENCODER_JAVASCRIPT)) {
formatter = new JavaScriptEncodingFormatter();
}
else if (encode.equalsIgnoreCase(ENCODER_NAMEPART)) {
formatter = UniqueNamePartFormatter.INSTANCE;
}
else if (encode.equalsIgnoreCase(ENCODER_URL)) {
formatter = new URLEncodingFormatter();
}
else {
ModuleDefinition modDef = null;
Class formatterClass = _systemFormatters.get(encode);
if (formatterClass == null) {
formatterClass = _customFormatters.get(encode);
}
if (formatterClass == null) {
modDef = getModuleRegistry().getModuleDefinitionByKey(WebTMLEncoderModuleType.class, encode);
if (modDef != null) {
try {
modDef.testDependencies();
}
catch (ModuleDependencyException e) {
throw new FormattingException("WebTML encoder '" + encode + "' not available bc. of missing dependency: " + e.getMessage());
}
formatterClass = modDef.getImplementationClass();
}
}
if (formatterClass != null) {
try {
if (modDef != null) {
formatter = (ObjectFormatter) getModuleRegistry().instantiate(modDef);
}
else {
formatter = (ObjectFormatter) formatterClass.newInstance();
}
}
catch (Exception e) {
throw new FormattingException("The encoder class " + formatterClass.getName() + " is not instantiable", e);
}
}
else {
throw new FormattingException("Unknown encoder " + encode);
}
}
if (formatter instanceof TMLContextAwareFormatter) {
((TMLContextAwareFormatter) formatter).setContext(context);
}
return formatter;
}
public synchronized String tmlCacheDump() throws IOException {
File outFile = new File(System.getProperty("user.home"), "tmlcachedump_" + new SimpleDateFormat("yyyyMMddHHmmSS").format(new Date()) + ".csv");
FileWriter out = new FileWriter(outFile);
getWebTMLCache().dump(out);
out.flush();
out.close();
return outFile.getPath();
}
public File getLicenseFile() {
return licenseFile;
}
public static WGACore retrieve(PageContext pageContext) {
return (WGACore) pageContext.getAttribute(ATTRIB_CORE, PageContext.APPLICATION_SCOPE);
}
public static WGACore retrieve(ServletContext servletContext) {
return (WGACore) servletContext.getAttribute(ATTRIB_CORE);
}
public boolean isTemporary() {
return false;
}
public static ClassLoader getLibraryLoader() {
return libraryClassLoadingChain;
}
public static List getDebugDocumentsList(HttpSession session) {
synchronized (session) {
List debugDocuments = (List) session.getAttribute(WGACore.ATTRIB_TMLDEBUG_DOCUMENTS);
if (debugDocuments == null) {
debugDocuments = new ArrayList();
session.setAttribute(WGACore.ATTRIB_TMLDEBUG_DOCUMENTS, debugDocuments);
}
return debugDocuments;
}
}
public boolean defaultActionSequenceIdAlreadyUsed(String sequenceId) {
try {
return (_calledSequenceIds.readEntry(sequenceId) != null);
}
catch (CacheException e) {
getLog().error("Exception determining action sequence id usage", e);
return false;
}
}
public void defaultActionCalledWithSequenceId(String sequenceId) {
try {
_calledSequenceIds.writeEntry(sequenceId, sequenceId);
}
catch (CacheException e) {
}
}
public List getSyncMappings() {
return syncMappings;
}
public synchronized void updateConfig() throws Exception {
configFileLastModified = configFile.lastModified();
parseConfigFile();
// Update general config
initReadGeneralConfig(true);
// Update filter mappings
initReadFilterMappings();
// Read domain configurations
Map<String, DomainConfiguration> newDomainConfigs = initReadDomains();
deployErrorPage();
// Update WGA plugin connections
updatePlugins(newDomainConfigs);
// Startup domain configurations (must be after plugin connection so that domains can use plugin-provided functionalities)
initStartupDomains(newDomainConfigs);
updateDatabaseServers();
// Deploy new content dbs, undeploy removed ones, update queries and
// mappings, update lucene config
updateContentDBs(true);
// Connect new personalisation dbs, disconnect removed ones, update user
// classes
updatePersonalisationDBs();
// Update jobs
updateScheduler();
// Update shares
updateShares();
initAccessLogger();
initExternalFileServing();
}
private void initExternalFileServing() {
String enabled = getWgaConfiguration().getServerOptions().get(WGAConfiguration.SERVEROPTION_EXTERNAL_FILE_SERVING_ENABLED);
if (enabled != null) {
_externalFileServingConfig.setEnabled(WGUtils.stringToBoolean(enabled));
}
if (getWgaConfiguration().getServerOptions().get(WGAConfiguration.SERVEROPTION_EXTERNAL_FILE_SERVING_DIRECTORY) != null) {
File dir = new File((String)getWgaConfiguration().getServerOptions().get(WGAConfiguration.SERVEROPTION_EXTERNAL_FILE_SERVING_DIRECTORY));
_externalFileServingConfig.setDirectory(dir);
} else if (_externalFileServingConfig.isEnabled()) {
getLog().warn("Mandantory option '" + WGAConfiguration.SERVEROPTION_EXTERNAL_FILE_SERVING_DIRECTORY + "' is missing. External file serving will be disabled.");
_externalFileServingConfig.setEnabled(false);
}
if (getWgaConfiguration().getServerOptions().get(WGAConfiguration.SERVEROPTION_EXTERNAL_FILE_SERVING_ROOT_URL) != null) {
String url = (String)getWgaConfiguration().getServerOptions().get(WGAConfiguration.SERVEROPTION_EXTERNAL_FILE_SERVING_ROOT_URL);
url = url.trim();
if (!url.endsWith("/")) {
url += "/";
}
_externalFileServingConfig.setRootURL(url);
}
if (getWgaConfiguration().getServerOptions().get(WGAConfiguration.SERVEROPTION_EXTERNAL_FILE_SERVING_THRESHOLD) != null) {
try {
_externalFileServingConfig.setThreshold(Long.parseLong((String)getWgaConfiguration().getServerOptions().get(WGAConfiguration.SERVEROPTION_EXTERNAL_FILE_SERVING_THRESHOLD)) * 1024);
}
catch (Exception e) {
_externalFileServingConfig.setThreshold(ExternalFileServingConfig.DEFAULT_THRESHOLD);
getLog().warn("Unable to parse external file serving threshold as long. Using default value " + _externalFileServingConfig.getThreshold() / 1024 + "kb.", e);
}
} else {
_externalFileServingConfig.setThreshold(ExternalFileServingConfig.DEFAULT_THRESHOLD);
}
if (_externalFileServingConfig.isEnabled()) {
if (!_externalFileServingConfig.getDirectory().exists()) {
_externalFileServingConfig.getDirectory().mkdirs();
}
if (!_externalFileServingConfig.getDirectory().exists() || !_externalFileServingConfig.getDirectory().canWrite()) {
getLog().warn("External file serving directory '" + _externalFileServingConfig.getDirectory().getAbsolutePath() + "' does not exists, could not be created or is not writable. External file serving will be disabled.");
_externalFileServingConfig.setEnabled(false);
}
}
}
private void deployErrorPage() {
// deploy error page
if (_wgaConfiguration.isCustomErrorPageEnabled() && _wgaConfiguration.getCustomErrorPage() != null) {
try {
this.log.info("Deploying custom error page.");
_errorPage = getDeployer().deployErrorPage(_wgaConfiguration.getCustomErrorPage());
}
catch (IOException e) {
this.log.error("Error deploying error page.", e);
}
}
}
private void unDeployErrorPage() {
if (_errorPage != null) {
String erroPagePath = getServletContext().getRealPath(_errorPage);
File errorPage = new File(erroPagePath);
if (errorPage.exists()) {
errorPage.delete();
}
}
}
public synchronized void updatePlugins(Map<String, DomainConfiguration> domainConfigs) {
Set newConnectedDBKeys = new HashSet();
if (_wgaDataDir == null) {
getLog().warn("Unable to handle WGA plugins bc. the WGA data dir could not be initialized!");
return;
}
getLog().info("Handling WGA plugins");
try {
WGFactory.getInstance().closeSessions();
// Create plugins base dir
File pluginsDir = new File(_wgaDataDir, "plugins");
if (!pluginsDir.exists() && !pluginsDir.mkdir()) {
getLog().error("Could not create plugins directory '" + pluginsDir.getPath() + "'. No WGA Plugins will be connected.");
return;
}
// Load plugins definition file
File pluginsDefFile = new File(pluginsDir, "plugins.xml");
WGAPluginSet currentPlugins;
boolean reinstallPluginsDir = false;
if (pluginsDefFile.exists()) {
currentPlugins = WGAPluginSet.load(pluginsDefFile);
}
else {
currentPlugins = new WGAPluginSet();
reinstallPluginsDir = true;
}
currentPlugins.init(this, pluginsDir);
if (this.pluginSet != null) {
currentPlugins.importRuntimeContexts(this.pluginSet);
}
// Replace plugins field with new plugin set - This must be done before connecting plugins so plugin init/connection scripts can
// refer to already installed plugins
this.pluginSet = currentPlugins;
// Cope with default plugins. Install new, uninstall removed (must be in that order so installation can determine status of previous version)
installDefaultPlugins(currentPlugins, reinstallPluginsDir);
uninstallRemovedDefaultPlugins();
// Validate and connect plugins
currentPlugins.validatePlugins();
newConnectedDBKeys = currentPlugins.connectPlugins(domainConfigs);
// Save plugins def file
this.pluginSet.save();
// Update module registry if it is already available
if (_moduleRegistry != null) {
updateModuleDefinitions(false);
}
}
catch (Throwable e) {
getLog().error("Error initializing plugins", e);
}
return;
}
private boolean uninstallRemovedDefaultPlugins() {
boolean anythingRemoved = false;
for (WGAPlugin plugin : getPluginSet().getPlugins()) {
if (plugin.isDefaultPlugin() || plugin.getRegisteredFilePath().contains("${wga.devpluginsdir}")) {
if (!plugin.getPluginFile().exists()) {
if (plugin.isActive()) {
try {
getPluginSet().deactivatePlugin(plugin);
disconnectPlugin(plugin);
}
catch (Exception e) {
getLog().error("Exception disabling removed default plugin", e);
}
}
getPluginSet().uninstallPlugin(plugin, false);
anythingRemoved = true;
}
}
}
if (anythingRemoved) {
try {
getPluginSet().save();
}
catch (Exception e) {
getLog().error("Exception uninstalling removed default plugins", e);
}
}
return anythingRemoved;
}
public synchronized void updatePlugins() {
updatePlugins(this.domainConfigs);
}
private boolean installDefaultPlugins(WGAPluginSet currentPlugins, boolean reinstallPluginsFolder) throws FileSystemException, MalformedURLException {
try {
boolean anythingInstalled = false;
// Reinstall the plugins folder if told to
if (reinstallPluginsFolder) {
File pluginsFolder = currentPlugins.getPluginFilesDir();
File[] files = pluginsFolder.listFiles();
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (!file.getName().endsWith(PluginConfig.WGAPLUGIN_SUFFIX)) {
continue;
}
try {
WGAPlugin.Configuration config = WGAPlugin.loadConfiguration(file);
currentPlugins.installPlugin(file, WGAPluginSet.UPDATESTRATEGY_UPDATE_KEEP_DATA, false);
anythingInstalled = true;
}
catch (Exception e) {
getLog().error("Exception installing plugin file " + file.getName(), e);
}
}
}
// STEP 1: Collect all default plugins to priorize identical plugins from different locations
Map<PluginID,File> defaultPlugins = new LinkedHashMap<PluginID, File>();
// Default plugins from within WGA distribution
Iterator defPlugins = getServletContext().getResourcePaths("/WEB-INF/default-plugins/").iterator();
File managementPluginFile = null;
while (defPlugins.hasNext()) {
String pluginPath = (String) defPlugins.next();
URL pluginURL = getServletContext().getResource(pluginPath);
if (pluginURL == null) {
continue;
}
// Previous to installation, check if the plugin is already installed, cancel if so. We want to fail silently here.
String fileName = pluginURL.getFile();
int lastSlashPos = fileName.lastIndexOf("/");
if (lastSlashPos != -1) {
fileName = fileName.substring(lastSlashPos + 1);
}
if (!fileName.endsWith(PluginConfig.WGAPLUGIN_SUFFIX)) {
continue;
}
File pluginFile = new File(getServletContext().getRealPath(pluginPath));
if (pluginFile.getName().contains("de.innovationgate.Management-")) {
managementPluginFile = pluginFile;
}
try {
WGAPlugin.Configuration config = WGAPlugin.loadConfiguration(pluginFile);
if (config != null) {
defaultPlugins.put(config.getCsConfig().getPluginConfig().getId(), pluginFile);
}
}
catch (Exception e) {
getLog().error("Exception installing registering plugin file " + pluginFile.getName() + " for installation", e);
}
}
// Additionally custom folder for default plugins
String customDefaultPlugins = System.getProperty(SYSPROPERTY_DEFAULT_PLUGINS);
if (customDefaultPlugins != null) {
File pluginsFolder = getWGAFile(customDefaultPlugins);
if (pluginsFolder != null && pluginsFolder.isDirectory()) {
File[] files = pluginsFolder.listFiles();
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (!file.getName().endsWith(PluginConfig.WGAPLUGIN_SUFFIX)) {
continue;
}
try {
WGAPlugin.Configuration config = WGAPlugin.loadConfiguration(file);
if (config != null) {
defaultPlugins.put(config.getCsConfig().getPluginConfig().getId(), file);
}
}
catch (Exception e) {
getLog().error("Exception installing registering plugin file " + file.getName() + " for installation", e);
}
}
}
else {
getLog().error("The default plugins folder '" + customDefaultPlugins + "' does not exist or is no directory");
}
}
// Folder with "developer plugins", i.e. design directories containing plugin code
String devPlugins = getDeveloperPluginsPath();
if (devPlugins != null) {
File pluginsFolder = getWGAFile(devPlugins);
if (pluginsFolder != null && pluginsFolder.isDirectory()) {
File[] files = pluginsFolder.listFiles();
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (!file.isDirectory()) {
if (!file.getName().endsWith(PluginConfig.WGAPLUGIN_SUFFIX)) {
continue;
}
}
File resolvedFile = WGUtils.resolveDirLink(file);
try {
WGAPlugin.Configuration config = WGAPlugin.loadConfiguration(resolvedFile);
if (config != null) {
defaultPlugins.put(config.getCsConfig().getPluginConfig().getId(), resolvedFile);
}
}
catch (Exception e) {
getLog().error("Exception installing registering plugin file " + resolvedFile.getName() + " for installation", e);
}
}
}
else {
getLog().error("The default plugins folder '" + devPlugins + "' does not exist or is no directory");
}
}
// STEP 2: Actually install collected default plugins - only one plugin per uname/version
for (File file : defaultPlugins.values()) {
if (installDefaultPlugin(currentPlugins, file)) {
anythingInstalled = true;
}
}
// STEP 3: Try to ensure that a Management plugin is installed and active
List<WGAPlugin> mgmtPlugins = currentPlugins.getPluginsByUniqueName("de.innovationgate.Management");
boolean anythingActive = false;
for (WGAPlugin plugin : mgmtPlugins) {
if (plugin.isActive() && plugin.isValid()) {
anythingActive = true;
break;
}
}
if (!anythingActive && managementPluginFile != null) {
currentPlugins.installPlugin(managementPluginFile, WGAPluginSet.UPDATESTRATEGY_UPDATE_KEEP_DATA, true);
anythingInstalled = true;
}
return anythingInstalled;
}
catch (PluginException e) {
if (e.getCause() != null) {
getLog().error("Error installing default plugins", e);
}
else {
getLog().error("Error installing default plugins: " + e.getMessage());
}
return false;
}
}
private boolean installDefaultPlugin(WGAPluginSet currentPlugins, File file) {
try {
WGAPlugin.Configuration config = WGAPlugin.loadConfiguration(file);
if (config == null) {
return false;
}
// Look if the plugin is already installed
PluginID defaultPluginId = config.getCsConfig().getPluginConfig().getId();
List<WGAPlugin> installedPlugins = currentPlugins.getPluginsByUniqueName(defaultPluginId.getUniqueName());
for (WGAPlugin plugin : installedPlugins) {
// Same plugin file = plugin already installed
if (plugin.getPluginFile().equals(file)) {
return false;
}
// Don't overwrite (active) dev plugin dirs
if (plugin.isDirectory() && plugin.isActive()) {
return false;
}
// Skip reasons that do not apply to dev plugins
if (!file.isDirectory()) {
// Don't overwrite (active) plugins that are of higher version
int versionComparison = plugin.getPluginID().getVersion().compareTo(defaultPluginId.getVersion());
if (versionComparison > 0 && plugin.isActive()) {
return false;
}
// Don't overwrite (active) plugins of same version and same or higher build
if (versionComparison == 0 && plugin.isActive() && plugin.getPluginID().getVersion().getBuildVersion() >= defaultPluginId.getVersion().getBuildVersion()) {
return false;
}
}
}
currentPlugins.installPlugin(file, WGAPluginSet.UPDATESTRATEGY_UPDATE_KEEP_DATA, true);
return true;
}
catch (Exception e) {
getLog().error("Exception installing default plugin file " + file.getName(), e);
return false;
}
}
/**
* This method creates a file path to the given file that, if possible, is relative to the current WGA runtime folders.
* If the file is below any WGA configation paths the path returned will be relative to it and so independent of the
* absolute location of the WGA configuration. The WGA configuration folders are then represented as path variables.
* If the file is not below any WGA Configuration path the absolute file path is returned.
* You must use method {@link #getWGAFile(String)} to resolve the paths created by this method and retrieve the file again
* @param file
* @return
*/
public String createWGAFilePath(File file) {
try {
String devPluginsPath = getDeveloperPluginsPath();
if (devPluginsPath != null) {
String path = WGUtils.relativeFilePath(file.getAbsolutePath(), devPluginsPath);
return "${wga.devpluginsdir}/" + path;
}
}
catch (IllegalArgumentException e) {
}
try {
String path = WGUtils.relativeFilePath(file.getAbsolutePath(), getWgaDataDir().getAbsolutePath());
return "${wga.datadir}/" + path;
}
catch (IllegalArgumentException e) {
}
try {
String path = WGUtils.relativeFilePath(file.getAbsolutePath(), getConfigFilePath());
return "${wga.cfgdir}/" + path;
}
catch (IllegalArgumentException e) {
}
try {
String path = WGUtils.relativeFilePath(file.getAbsolutePath(), getServletContext().getRealPath("/WEB-INF/default-plugins"));
return "${wga.defaultpluginsdir}/" + path;
}
catch (IllegalArgumentException e) {
}
return file.getAbsolutePath();
}
public WGDatabase connectPlugin(WGAPlugin plugin, Map domainConfigs) throws InvalidPluginException, WGIllegalArgumentException, FileSystemException, IOException {
// Look if already connected to the correct file
String dbKey = plugin.buildDatabaseKey();
WGDatabase db = contentdbs.get(dbKey);
if (db != null) {
try {
Long pluginFileTime = (Long) db.getAttribute(DBATTRIB_PLUGIN_FILETIME);
Version pluginVersion = (Version) db.getAttribute(DBATTRIB_PLUGIN_VERSION);
if (pluginVersion.equals(plugin.getPluginID().getVersion()) &&
(pluginFileTime != null && pluginFileTime.equals(new Long(plugin.getFileLastModified())))) {
if (!db.isSessionOpen()) {
db.openSession();
}
return db;
}
else {
removeContentDB(dbKey);
db = null;
}
}
catch (Exception e) {
throw new InvalidPluginException(plugin, "Error checking existent plugin database " + dbKey, e);
}
}
if (!plugin.isActive()) {
throw new InvalidPluginException(plugin, "Plugin is deactivated");
}
if (!plugin.isValid()) {
throw new InvalidPluginException(plugin, "Plugin is invalid");
}
// First connect all mandatory plugins
try {
Iterator mandatoryPlugins = plugin.getMandatoryPlugins().values().iterator();
while (mandatoryPlugins.hasNext()) {
WGAPlugin mandatoryPlugin = (WGAPlugin) mandatoryPlugins.next();
connectPlugin(mandatoryPlugin, domainConfigs);
}
}
// A mandatory plugin is invalid. Cancel connect.
catch (InvalidPluginException e) {
throw e;
}
logCategoryInfo("Plugin " + plugin.getInstallationKey(), 2);
// Mandatory db options (for plugins)
Map<String, String> dbOptions = new HashMap<String, String>();
dbOptions.put(WGDatabase.COPTION_DBREFERENCE, dbKey.toLowerCase());
dbOptions.put(WGDatabase.COPTION_READERPROFILECREATION, "true");
dbOptions.put(WGDatabase.COPTION_USERCACHELATENCY, String.valueOf(_wgaConfiguration.getUserCacheLatencyMinutes()));
// We try to automatically migrate plugin content stores to CS5 format
dbOptions.put(WGDatabase.COPTION_CONTENT_STORE_VERSION, String.valueOf(WGDatabase.CSVERSION_WGA5));
// Clear the plugin database before connecting if the plugin is updated and should clear the db on update
if (plugin.getRuntimeContext().isUpdated()) {
if (plugin.getCsConfig().getPluginConfig() instanceof de.innovationgate.wga.common.beans.csconfig.v3.PluginConfig) {
de.innovationgate.wga.common.beans.csconfig.v3.PluginConfig v3Config = (de.innovationgate.wga.common.beans.csconfig.v3.PluginConfig) plugin.getCsConfig().getPluginConfig();
if (v3Config.isClearDatabaseOnUpdate()) {
getLog().info("Clearing plugin database for installation key " + plugin.getInstallationKey());
plugin.getParent().deletePluginDatabase(plugin);
}
}
plugin.getRuntimeContext().setUpdated(false);
}
// Connect
getLog().info("Connecting plugin " + plugin.getPluginID().getUniqueName() + " Version " + plugin.getPluginID().getVersion().toString());
try {
db = WGFactory.getInstance().openDatabase(null, de.innovationgate.webgate.api.hsql.WGDatabaseImpl.class.getName(), plugin.buildDatabasePath(), null, null, dbOptions);
}
catch (Throwable e1) {
throw new InvalidPluginException(plugin, "Could not connect plugin \"" + plugin.getPluginID().getUniqueName() + "\"", e1);
}
if (db == null || !db.isSessionOpen()) {
throw new InvalidPluginException(plugin, "Could not connect plugin \"" + plugin.getPluginID().getUniqueName() + "\" - Check logged messages above for error details");
}
try {
db.getSessionContext().setTask("Initializing database in WGA");
// Plugin dbs are always CS5 since they are automatically migrated
//getLog().info("Database of plugin " + plugin.getPluginID().getUniqueName() + " is content store version " + db.getContentStoreVersion());
PluginConfig pc = plugin.getCsConfig().getPluginConfig();
String auth = pc.getAuthentication();
db.setTitle(pc.getTitle());
// Set mandatory database attributes
initializeDBAttributes(db, dbKey, dbKey, new HashSet());
// Create authentication
if (auth != null) {
String authImplClass = null;
Map<String,String> authOptions = new HashMap<String, String>();
// Delegate authentication to the default domain
if (auth.equals(PluginConfig.AUTHSOURCE_DEFAULT_DOMAIN)) {
authImplClass = WGAAuthModuleFactory.AUTHMODULE_DELEGATE;
authOptions.put(DelegatingAuthModule.COPTION_DOMAIN, "default");
}
// Use some plugin for authentication
else {
WGAPlugin authPlugin = plugin.getParent().getPluginByUniqueName(auth);
if (authPlugin != null) {
authImplClass = CSAuthModule.class.getName();
authOptions.put(CSAuthModule.COPTION_DBKEY, authPlugin.buildDatabaseKey());
}
else {
getLog().error("Unable to find authentication plugin " + auth);
}
}
if (authImplClass != null) {
AuthenticationModule authModule = WGFactory.getAuthModuleFactory().getAuthModule(authImplClass, authOptions, db);
db.setAuthenticationModule(authModule);
}
}
// Enforce some plugin settings via db attributes
db.setAttribute(DBATTRIB_PERSMODE, String.valueOf(pc.getPersonalisationMode()));
db.setAttribute(DBATTRIB_PERSSTATMODE, String.valueOf(Constants.PERSSTATMODE_SESSION));
db.setAttribute(DBATTRIB_PLUGIN_FILETIME, new Long(plugin.getFileLastModified()));
db.setAttribute(DBATTRIB_PLUGIN_ID, plugin.getPluginID());
db.setAttribute(DBATTRIB_PLUGIN_VERSION, plugin.getPluginID().getVersion());
if (!pc.isUsageAsContentStore()) {
db.setAttribute(DBATTRIB_ALLOW_PUBLISHING, "false");
}
if (!pc.isShowOnStartPage()) {
db.setAttribute(DBATTRIB_STARTPAGE, "false");
}
// Configure design provider
DesignReference ref = new DesignReference(Constants.DESIGNCOL_PLUGIN, plugin.getInstallationKey(), null);
db.setDesignProvider(new FileSystemDesignProvider(ref, this, db, plugin.getDesignURL().toString(), Collections.EMPTY_MAP));
db.setAllowDesignModification(false);
// Determine if ACL is empty
boolean aclEmpty = false;
try {
if (db.isConnected() && db.hasFeature(WGDatabase.FEATURE_ACL_MANAGEABLE) && db.getACL().getAllEntries().size() == 0) {
aclEmpty = true;
}
}
catch (WGBackendException e1) {
getLog().error("Error retrieving ACL state of db '" + db.getDbReference() + "'", e1);
}
// Process system container
SystemContainerManager.SystemContainerContext scContext = null;
try {
scContext = _systemContainerManager.addDatabase(db, plugin, aclEmpty);
}
catch (Exception e) {
this.log.error("Exception processing system file container for plugin '" + plugin.getPluginID().getUniqueName() + "'", e);
}
// Build map of publisher options from wga.xml. We only use gobal options here since plugins have no own options in wga.xml
// and csconfig.xml options are processed via system container
Map<String, String> publisherOptions = new HashMap<String, String>();
// publisherOptions.putAll(_globalPublisherOptions); Plugins should not be influenced by global options of the current configuration
if (scContext != null) {
scContext.putPublisherOptions(publisherOptions);
}
// Publisher options initialisation which is equal for content dbs and plugins
processPublisherOptions(db, publisherOptions);
// Set plugin homepage. The method chooses either the plugin-specific homepage or the publisher option
// Must be after publisher option initialisation to be able to react on them
db.setAttribute(DBATTRIB_HOME_PAGE, plugin.getPluginHomepage());
// check if db is empty before hdb script runs
boolean isEmptyDB = db.isContentEmpty();
// Validate default language definition
if (!isEmptyDB) {
db.determineDefaultLanguage();
}
// System container initialisations
if (scContext != null) {
scContext.performInitialisation(new Boolean(isEmptyDB));
if (isEmptyDB) {
db.onConnect(new ValidateDefaultLanguageAction());
}
}
// Registering connection
this.contentdbs.put(db.getDbReference(), db);
performNewDBOperations(db);
// Mark this database as fully connected
db.setAttribute(DBATTRIB_FULLY_CONNECTED, "true");
// Initially create field mappings. These can only come from csconfig.xml for plugins
updateFieldMappings(db, null);
return db;
}
catch (Throwable e) {
try {
db.close();
}
catch (WGAPIException e2) {
// Silent failure of closing an uninitialized plugin bc. the connection failure is more important
}
plugin.setValid(false);
throw new InvalidPluginException(plugin, "Error connecting plugin" ,e);
}
}
private void processPublisherOptions(WGDatabase db, Map<String, String> publisherOptions) {
// Put some default options for internal use
db.setAttribute(DBATTRIB_STORED_QUERIES, new HashMap());
db.setAttribute(DBATTRIB_META_MAPPINGS, new HashMap());
db.setAttribute(DBATTRIB_ITEM_MAPPINGS, new HashMap());
db.setAttribute(DBATTRIB_PLUGIN_SHORTCUTS, new HashMap());
// Create a file cache object.
try {
db.setAttribute(WGACore.DBATTRIB_FILECACHE, new FileCache(db, this));
}
catch (CacheException e) {
getLog().error("Error initializing file cache for database " + db.getDbReference(), e);
};
// Put publisher options
Iterator<String> optionKeys = publisherOptions.keySet().iterator();
while (optionKeys.hasNext()) {
String optionName = optionKeys.next();
String optionValue = publisherOptions.get(optionName);
db.setAttribute(optionName, optionValue);
}
// CS Only initialisations
if (db.hasFeature(WGDatabase.FEATURE_FULLCONTENTFEATURES)) {
// Fetch design encoding
String currentDesignEncoding = (String) WGUtils.getValueOrDefault(db.getAttribute(DBATTRIB_DESIGN_ENCODING), Charset.defaultCharset().name());
// design encoding changed
// this is used for SC_NOT_MODIFIED in WGPDispatcher
if (getLastDesignEncoding(db.getDbReference()) == null || !getLastDesignEncoding(db.getDbReference()).equals(currentDesignEncoding)) {
setLastDesignEncoding(db.getDbReference(), currentDesignEncoding);
}
// Initialize title path url manager
try {
TitlePathManager titlePathManager = new TitlePathManager(db, this, db.getBooleanAttribute(DBATTRIB_TITLEPATHURL, false));
db.setAttribute(DBATTRIB_TITLEPATHMANAGER, titlePathManager);
}
catch (Exception e) {
getLog().error("Error initializing title path manager for database " + db.getDbReference(), e);
}
// Determine language behaviour
LanguageBehaviour langBehaviour = createLanguageBehaviour(db);
db.setAttribute(WGACore.DBATTRIB_LANGUAGEBEHAVIOUR_INSTANCE, langBehaviour);
}
// Non-CS only initialisations
else {
db.setAttribute(WGACore.DBATTRIB_LANGUAGEBEHAVIOUR_INSTANCE, new OnlyDefaultLanguageBehaviour());
}
}
private LanguageBehaviour createLanguageBehaviour(WGDatabase db) {
String langBehaviourName = (String) db.getAttribute(WGACore.DBATTRIB_LANGUAGEBEHAVIOUR);
if (langBehaviourName == null) {
boolean isMultiLanguage = db.getBooleanAttribute(WGACore.DBATTRIB_MULTILANGUAGE_CONTENT, true);
if (isMultiLanguage) {
langBehaviourName = StaticLanguageBehaviour.class.getName();
}
else {
langBehaviourName = OnlyDefaultLanguageBehaviour.class.getName();
}
}
// Convert pre OpenWGA 5.1 values to their 5.1 pendants
else {
if (langBehaviourName.equals("default")) {
langBehaviourName = DynamicLanguageBehaviour.class.getName();
}
else if (langBehaviourName.equals("maincontent")) {
langBehaviourName = StaticLanguageBehaviour.class.getName();
}
else if (langBehaviourName.equals("browser")) {
langBehaviourName = OnlyDefaultLanguageBehaviour.class.getName();
}
}
LanguageBehaviour langBehaviour;
// For applications
if (getModuleRegistry() != null) {
ModuleDefinition languageBehaviourMD = getModuleRegistry().getModuleDefinition(LanguageBehaviourModuleType.class, langBehaviourName);
if (languageBehaviourMD == null) {
getLog().error("Unable to load language behaviour " + langBehaviourName + ". Falling back to mode 'static'.");
languageBehaviourMD = getModuleRegistry().getModuleDefinition(LanguageBehaviourModuleType.class, StaticLanguageBehaviour.class);
}
try {
langBehaviour = (LanguageBehaviour) getModuleRegistry().instantiate(languageBehaviourMD);
}
catch (ModuleInstantiationException e) {
getLog().error("Exception instantiating language behaviour '" + languageBehaviourMD.getTitle(Locale.getDefault()) + "'. Falling back to mode 'static'.", e);
langBehaviour = new StaticLanguageBehaviour();
}
}
// For Plugins (no registry yet)
else {
try {
langBehaviour = (LanguageBehaviour) getLibraryLoader().loadClass(langBehaviourName).newInstance();
}
catch (Exception e) {
getLog().error("Exception instantiating language behaviour '" + langBehaviourName + "'. Falling back to mode 'static'.", e);
langBehaviour = new StaticLanguageBehaviour();
}
}
return langBehaviour;
}
public Scheduler getScheduler() {
return _scheduler;
}
public static String getBIClientString() {
return "BI/" + WGAVersion.WGAPUBLISHER_MAJOR_VERSION + "." + WGAVersion.WGAPUBLISHER_MINOR_VERSION + "." + WGAVersion.WGAPUBLISHER_MAINTENANCE_VERSION + "_"
+ WGAVersion.WGAPUBLISHER_BUILD_VERSION;
}
public static String getWebformClientString() {
return "Webform/" + WGAVersion.WGAPUBLISHER_MAJOR_VERSION + "." + WGAVersion.WGAPUBLISHER_MINOR_VERSION + "." + WGAVersion.WGAPUBLISHER_MAINTENANCE_VERSION + "_"
+ WGAVersion.WGAPUBLISHER_BUILD_VERSION;
}
public static String getBuildSignature() {
return _buildSignature;
}
public static boolean isFinalBuild() {
return _finalBuild;
}
/**
* @param wgaTempDir
*/
private void killTempDir(File wgaTempDir) {
Logger.getLogger("wga").info("Deleting temporary files");
WGUtils.delTree(wgaTempDir);
}
/**
* @return Returns the luceneManager.
*/
public LuceneManager getLuceneManager() {
return luceneManager;
}
public boolean isLuceneEnabled() {
return (luceneManager != null);
}
/**
* @deprecated use isAdminLoggedIn(HttpServletRequest) instead
* @param session
* @return
*/
public static boolean isAdminLoggedIn(HttpSession session) {
String adminName = (String) session.getAttribute(WGACore.SESSION_ADMINNAME);
return (adminName != null);
}
public boolean isAdminLoggedIn(HttpServletRequest request) {
// check if we should allow passwordless admin login from localhost
if (request != null && isLocalRequest(request) && Boolean.parseBoolean(System.getProperty(SYSPROP_SKIP_LOCAL_ADMIN_LOGINS, "false"))) {
return true;
} else if (request != null) {
String adminName = (String) request.getSession().getAttribute(WGACore.SESSION_ADMINNAME);
String adminPassword = (String) request.getSession().getAttribute(WGACore.SESSION_ADMINPASSWORD);
return isAdminLogin(adminName, adminPassword, request);
} else {
return false;
}
}
public Analyzer getAnalyzerForLanguageCode(String lang) {
return analyzerMappings.get(lang);
}
public Analyzer getDefaultAnalyzer() {
return defaultAnalyzer;
}
public FileHandler getFileHandlerForExtension(String extension) {
return fileHandlerMappings.get(extension.toLowerCase());
}
public boolean hasFileHandler(String extension) {
FileHandler handler = getFileHandlerForExtension(extension);
return handler != null;
}
public DomainConfiguration getDomainConfig(Map<String, DomainConfiguration> configs, String name) {
if (name.startsWith(PluginConfig.PLUGIN_DBKEY_PREFIX)) {
DomainConfiguration dc = new DomainConfiguration(name);
return dc;
}
return configs.get(name.toLowerCase());
}
public DomainConfiguration getDomainConfig(String name) {
// Prevent nullpointer when this is called before domain init in startup
if (this.domainConfigs != null) {
return getDomainConfig(this.domainConfigs, name);
}
else {
return null;
}
}
public DomainConfiguration getDomainConfigForDatabase(WGDatabase db) {
String domain = (String) db.getAttribute(DBATTRIB_DOMAIN);
return getDomainConfig(domain);
}
/**
* @return Returns the quartzScheduler.
*/
public org.quartz.Scheduler getQuartzScheduler() {
return _quartzScheduler;
}
/**
* @return Returns the userAgentVerifier.
*/
public UserAgentVerifier getUserAgentVerifier() {
return userAgentVerifier;
}
private String readOptionValue(Element dbOptionElem) throws IOException {
String optionValue = dbOptionElem.attributeValue("value");
String encoding = dbOptionElem.attributeValue("encode");
if (encoding != null) {
if (encoding.equals("base64")) {
optionValue = new String(Base64.decode(optionValue));
}
}
return optionValue;
}
public DESEncrypter getDesEncrypter() {
return desEncrypter;
}
public void setDesEncrypter(DESEncrypter desEncrypter) {
this.desEncrypter = desEncrypter;
}
public void addEventListener(WGACoreEventListener listener) {
if (!eventListeners.contains(listener)) {
eventListeners.add(listener);
}
}
public void removeEventListener(WGACoreEventListener listener) {
eventListeners.remove(listener);
}
private void fireCoreEvent(WGACoreEvent event) {
// Set core status
if (event.getType() <= WGACoreEvent.WGACORE_STATE_MAXTYPE) {
_status = event.getType();
}
List listenersList = new ArrayList(eventListeners);
Iterator<WGACoreEventListener> listeners = listenersList.iterator();
while (listeners.hasNext()) {
WGACoreEventListener listener = listeners.next();
try {
switch (event.getType()) {
case WGACoreEvent.TYPE_CS_CONNECTED:
listener.contentStoreConnected(event);
break;
case WGACoreEvent.TYPE_CS_DISCONNECTED:
listener.contentStoreDisconnected(event);
break;
case WGACoreEvent.TYPE_STARTUP_PRE_CONNECT:
listener.startupPreConnect(event);
break;
case WGACoreEvent.TYPE_STARTUP_POST_CONNECT:
listener.startupPostConnect(event);
break;
case WGACoreEvent.TYPE_SHUTDOWN_PRE_DISCONNECT:
listener.shutdownPreDisconnect(event);
break;
case WGACoreEvent.TYPE_SHUTDOWN_POST_DISCONNECT:
listener.shutdownPostDisconnect(event);
break;
}
}
catch (Exception e) {
log.error("WGACoreEventListener '" + listener.getClass().getName() + "' failed with exception: " + e.getMessage(), e);
}
}
}
public WGAResourceBundleManager getResourceBundleManager(WGDatabase database) {
synchronized (database) {
WGAResourceBundleManager manager = (WGAResourceBundleManager) database.getAttribute(DBATTRIB_RESOURCEBUNDLE_MANAGER);
if (manager == null) {
manager = new WGAResourceBundleManager(database);
database.setAttribute(DBATTRIB_RESOURCEBUNDLE_MANAGER, manager);
}
return manager;
}
}
public TestCore getTestCore() {
return _testCore;
}
public Locale languageCodeToLocale(String prefLang) {
if (prefLang == null) {
return null;
}
return WGLanguage.languageNameToLocale(prefLang);
}
/**
* @return Returns the designSyncFileVerifier.
*/
public DesignFileValidator getDesignFileValidator() {
return designFileValidator;
}
public boolean isClientPermitted(WGDatabase db, HttpServletRequest request) {
if (db.getAttribute(DBATTRIB_CLIENTRESTRICTIONS) != null) {
IPv4Address ip;
try {
ip = new IPv4Address(request.getRemoteAddr());
if (!ip.validate()) {
log.info("Client ip '" + request.getRemoteAddr() + "' from last request is invalid. Client is not permitted to access db '" + db.getDbReference() + "'.");
return false;
}
}
catch (Exception e) {
// ip could not be parsed
log.info("Client ip '" + request.getRemoteAddr() + "' from last request is invalid. Client is not permitted to access db '" + db.getDbReference() + "'.");
return false;
}
boolean permitted = isClientPermitted(db, ip);
if (!permitted) {
log.info("Client ip '" + request.getRemoteAddr() + "' was not permitted to access db '" + db.getDbReference() + "'.");
}
return permitted;
}
else {
// if no restrictions client is permitted
return true;
}
}
public boolean isClientPermitted(WGDatabase db, IPv4Address ip) {
List clientRestrictions = (List) db.getAttribute(DBATTRIB_CLIENTRESTRICTIONS);
if (clientRestrictions != null) {
Iterator it = clientRestrictions.iterator();
while (it.hasNext()) {
de.innovationgate.utils.net.IPv4Restriction restriction = (de.innovationgate.utils.net.IPv4Restriction) it.next();
if (restriction.exists(ip)) {
return true;
}
}
return false;
}
else {
// if no restrictions client is permitted
return true;
}
}
/**
* @return Returns the bruteForceLoginBlocker.
*/
public BruteForceLoginBlocker getBruteForceLoginBlocker() {
return bruteForceLoginBlocker;
}
/**
* @return Returns the webserviceEnabled.
*/
public boolean isWebserviceEnabled() {
return _webserviceEnabled;
}
public boolean isAdministrativePort(int port) {
// If no admin ports configured administration is open
if (getWgaConfiguration().getAdminToolsPortRestrictions().size() == 0) {
return true;
}
for (Integer adminPort : getWgaConfiguration().getAdminToolsPortRestrictions()) {
if (adminPort.equals(port)) {
return true;
}
}
return false;
}
public boolean isAuthoringPort(int port) {
// If no authoring ports configured authoring is open
if (getWgaConfiguration().getAuthoringDesignAccessPortRestrictions().size() == 0) {
return true;
}
for (Integer authoringPort : getWgaConfiguration().getAuthoringDesignAccessPortRestrictions()) {
if (authoringPort.equals(port)) {
return true;
}
}
return false;
}
public String updateConfigDocument(Document newConfig) throws UnsupportedEncodingException, FileNotFoundException, IOException, ParserConfigurationException, DocumentException {
String newTimestamp = WGACore.DATEFORMAT_GMT.format(new Date());
newConfig.getRootElement().addAttribute("timestamp", newTimestamp);
OutputFormat outputFormat = OutputFormat.createPrettyPrint();
outputFormat.setTrimText(true);
outputFormat.setNewlines(true);
XMLWriter writer = new XMLWriter(new FileOutputStream(getConfigFile()), outputFormat);
writer.write(newConfig);
writer.close();
return newTimestamp;
}
public String getDesignDatabaseKey(WGDatabase db) {
WGDesignProvider prov = db.getDesignProvider();
if (prov instanceof DBDesignProvider) {
return ((DBDesignProvider) prov).getDesignDBKey();
}
else {
return db.getDbReference();
}
}
public String getDesignDatabaseKey(String dbkey) {
WGDatabase db = getContentdbs().get(dbkey);
if (db == null) {
return dbkey;
}
return getDesignDatabaseKey(db);
}
/**
* @deprecated since 4.1 the link encoding is equals getCharacterEncoding() - which defaults to UTF-8
* @return Returns the tmlLinkEncoding.
*/
public String getTmlLinkEncoding() {
return getCharacterEncoding();
}
/**
* @return Returns the usageStatistics.
*/
public WGAUsageStatistics getUsageStatistics() {
return _usageStatistics;
}
public void databaseConnected(WGDatabaseEvent event) {
getLog().info("Prepared database " + event.getDatabase().getDbReference() + " has been connected");
eventManager.updateDatabaseEvents(event.getDatabase());
}
/*
* (non-Javadoc)
*
* @see de.innovationgate.webgate.api.WGDatabaseConnectListener#databaseConnectionError(de.innovationgate.webgate.api.WGDatabaseEvent)
*/
public void databaseConnectionError(WGDatabaseEvent event) {
getLog().warn("Removing database " + event.getDatabase().getDbReference() + " because of failure of initial connection");
if (getContentdbs().containsValue(event.getDatabase())) {
removeContentDB(event.getDatabase().getDbReference());
}
else if (getPersonalisationdbs().containsValue(event.getDatabase())) {
removePersonalisationDB(getDomainConfigForDatabase(event.getDatabase()).getName());
}
}
public static String getConfigfileName() {
String fileName = System.getProperty(SYSPROPERTY_CONFIGFILE);
if (fileName != null) {
return fileName;
}
return CONFIGFILE_NAME;
}
public String getCharacterEncoding() {
if (_characterEncoding == null) {
// default to UTF-8
return "UTF-8";
} else {
return _characterEncoding;
}
}
public byte[] getLicenseData() throws WGSystemException {
if (licenseFile != null && licenseFile.exists()) {
try {
FileInputStream fin = new FileInputStream(licenseFile);
ByteArrayOutputStream out = new ByteArrayOutputStream();
WGUtils.inToOut(fin, out, 1024);
out.close();
return out.toByteArray();
}
catch (Exception e) {
throw new WGSystemException("Error reading license data.", e);
}
}
else {
return null;
}
}
/**
* checks if the given db is available, returns when database is available
* or timeout is reached
*
* @param dbKey -
* db to check for
* @param interval -
* interval in ms for checks
* @param timeout -
* timeout in ms for the method
* @return true if db is available, false if timeout has been reached
*/
public boolean waitForDatabase(String dbKey, long interval, long timeout) {
long startTime = System.currentTimeMillis();
boolean dbAvailable = getContentdbs().containsKey(dbKey.toLowerCase());
while (!dbAvailable && ((System.currentTimeMillis() - startTime) < timeout)) {
try {
Thread.sleep(interval);
}
catch (InterruptedException e) {
}
dbAvailable = getContentdbs().containsKey(dbKey.toLowerCase());
}
return dbAvailable;
}
public File getConfigFile() {
return configFile;
}
public void updateLibraryLoader() {
synchronized (libraryClassLoadingChain) {
_systemContainerManager.updateLibraryLoader(libraryClassLoadingChain);
}
}
public static IsolatedJARLoader getBaseLibraryLoader() {
return baseLibraryLoader;
}
/**
* Enforces all data in system file container that effects the whole WGA configuration.
* If the database got the system file container via DBDesignProvider, there is no need to process most of
* WGA wide configurations again, since they already were enforced by the design provider. So these operations
* are only executed when info.isFromProviderDB() is false.
* @param csConfig
*/
public void enforceCSConfig(WGDatabase db, ContainerInfo info) {
boolean bypassGlobalSettings = false;
if (db.getDesignProvider() != null && db.getDesignProvider() instanceof DBDesignProvider) {
bypassGlobalSettings = true;
}
// Update library loader. Can be bypassed if the system file container is from a provider DB.
if (!info.isFromProviderDB()) {
updateLibraryLoader();
info.setEnfordedLibraryUpdate(true);
}
// If no cxconfig.xml we are finished here
CSConfig csConfig = info.getCsConfig();
if (csConfig == null) {
return;
}
// WGA wide configurations, that can be bypassed if the system file container is from a provider DB
// (because they already were enforced by the provider db)
if (!info.isFromProviderDB()) {
// Add encoder mappings
Iterator encoderMappings = csConfig.getEncoderMappings().iterator();
while (encoderMappings.hasNext()) {
EncoderMapping mapping = (EncoderMapping) encoderMappings.next();
getLog().info("Adding WebTML encoder '" + mapping.getName() + "'");
if (addEncoderMapping(mapping.getName(), mapping.getImplementationClass(), false)) {
info.getEnforcedEncoderMappings().add(mapping.getName());
}
}
// Add element mappings
Iterator elementMappings = csConfig.getElementMappings().iterator();
while (elementMappings.hasNext()) {
ElementMapping mapping = (ElementMapping) elementMappings.next();
getLog().info("Adding WebTML element '" + mapping.getName() + "'");
if (addElementMapping(mapping.getName(), mapping.getImplementationClass(), false)) {
info.getEnforcedElementMappings().add(mapping.getName());
}
}
// Add media keys
Iterator mediaKeys = csConfig.getMediaKeys().iterator();
while (mediaKeys.hasNext()) {
de.innovationgate.wga.common.beans.csconfig.v1.MediaKey mediaKey = (de.innovationgate.wga.common.beans.csconfig.v1.MediaKey) mediaKeys.next();
getLog().info("Adding WebTML media key '" + mediaKey.getKey() + "' for MIME type '" + mediaKey.getMimeType() + "'");
addMediaMapping(mediaKey, false);
info.getEnforcedMediaMappings().add(mediaKey.getKey());
}
if (csConfig instanceof de.innovationgate.wga.common.beans.csconfig.v2.CSConfig) {
// Add TMLScript global shortcuts
de.innovationgate.wga.common.beans.csconfig.v2.CSConfig v2 = (de.innovationgate.wga.common.beans.csconfig.v2.CSConfig) csConfig;
Iterator shortcuts = v2.getShortcuts().iterator();
while (shortcuts.hasNext()) {
Shortcut shortcut = (Shortcut) shortcuts.next();
if (shortcut.getType() == Shortcut.TYPE_TMLSCRIPT_GLOBAL) {
getTmlscriptGlobalRegistry().registerGlobal(new TMLScriptGlobal(shortcut.getShortcut(), TMLScriptGlobal.TYPE_PACKAGE_OR_CLASS, shortcut.getReference()));
}
}
}
}
// Set WGA version compliance if not explicitly set via first level db option
Set firstLevelOptions = (Set) db.getAttribute(DBATTRIB_FIRSTLEVELDBOPTIONS);
if (!firstLevelOptions.contains(WGDatabase.COPTION_NOITEMBEHAVIOUR)) {
db.getNoItemBehaviour().compliantTo(csConfig.getVersionCompliance());
}
// Add jobs
Iterator jobs = csConfig.getJobDefinitions().iterator();
while (jobs.hasNext()) {
JobDefinition job = (JobDefinition) jobs.next();
String jobName = db.getDbReference() + "." + job.getName();
try {
Task task = null;
if (job.getType() == JobDefinition.TYPE_TMLSCRIPTMODULE) {
ScriptTask scriptTask = new ScriptTask();
scriptTask.setCancelJobOnFail(true);
scriptTask.setDatabase(db.getDbReference());
scriptTask.setModule(job.getResource());
task = scriptTask;
}
else if (job.getType() == JobDefinition.TYPE_JAVA) {
JavaTask javaTask = new JavaTask();
javaTask.setClassName(job.getResource());
task = javaTask;
}
else {
getLog().error("Error adding job '" + jobName + "'. Unknown job type: " + job.getType());
continue;
}
task.setDescription(job.getDescription());
JobSchedule schedule = null;
if (job.getSchedule() != null && !job.getSchedule().trim().equals("")) {
schedule = new JobSchedule();
schedule.setEnabled(true);
schedule.setScheduleData(job.getSchedule());
schedule.setType(JobSchedule.TYPE_CRON);
}
Job schedulerJob = getScheduler().addCustomTaskJob(jobName, task, false, schedule);
schedulerJob.setDescription(job.getDescription());
schedulerJob.getOptions().put("database", db.getDbReference());
info.getEnforcedJobDefinitions().add(schedulerJob.getName());
}
catch (Exception e) {
getLog().error("Error adding job '" + jobName + "' from content store configuration", e);
}
}
}
protected boolean addMediaMapping(MediaKey mediaKey, boolean system) {
if (system) {
this.systemMediaKeys.put(mediaKey.getKey(), mediaKey);
return true;
}
else if (systemMediaKeys.containsKey(mediaKey.getKey())) {
MediaKey key = systemMediaKeys.get(mediaKey.getKey());
if (!key.equals(mediaKey)) {
getLog().warn("Cannot add media key '" + mediaKey.getKey() + "' because the key is already used in WGA configuration with different data");
}
return false;
}
else {
this.customMediaKeys.put(mediaKey.getKey(), mediaKey);
return true;
}
}
public InputStream dumpContentStore(WGDatabase dbSource, String filterExpression, boolean autoCorrect, Logger log) throws WGAPIException, IOException {
return dumpContentStore(dbSource, filterExpression, autoCorrect, log, false);
}
public InputStream dumpContentStore(WGDatabase dbSource, String filterExpression, boolean autoCorrect, Logger log, boolean includeACL) throws WGAPIException, IOException {
return dumpContentStore(dbSource, filterExpression, autoCorrect, log, includeACL, false);
}
public InputStream dumpContentStore(WGDatabase dbSource, String filterExpression, boolean autoCorrect, Logger log, boolean includeACL, boolean includeSystemAreas) throws WGAPIException, IOException {
log.info("Creating dump database");
// Create working folder for dump database
File dir = File.createTempFile("csd", ".tmp", WGFactory.getTempDir());
dir.delete();
dir.mkdir();
// Create dump database
Map<String, String> options = new HashMap<String, String>();
options.put(WGDatabase.COPTION_MONITORLASTCHANGE, "false");
WGDatabase dbTarget = WGFactory.getInstance().openDatabase(null, de.innovationgate.webgate.api.hsql.WGDatabaseImpl.class.getName(), dir.getAbsolutePath() + "/wgacs", "sa", null, options);
dbTarget.setDbReference("Temporary WGACS dump target");
// Replicate
log.info("Synchronizing data to dump database");
dbSource.lock();
try {
ContentStoreDumpManager importer = new ContentStoreDumpManager(dbSource, dbTarget, log);
importer.exportDump(includeACL, includeSystemAreas);
}
finally {
dbSource.unlock();
}
// Close database and zip up its contents
log.info("Creating dump file");
dbTarget.close();
File zipFile = File.createTempFile("csz", ".tmp", WGFactory.getTempDir());
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
out.setLevel(9);
File[] files = dir.listFiles();
for (int i = 0; i < files.length; i++) {
File file = files[i];
out.putNextEntry(new ZipEntry(file.getName()));
InputStream in = new BufferedInputStream(new FileInputStream(file));
WGUtils.inToOut(in, out, 2048);
in.close();
out.closeEntry();
}
out.close();
// Delete temp dir
WGUtils.delTree(dir);
// Return input stream for zip file
return new TempFileInputStream(zipFile);
}
public String runTransientTask(String taskImplementation, String taskName, Map options) throws ClassNotFoundException, InstantiationException, IllegalAccessException, JobFailedException, ConfigurationException {
Class clazz = Class.forName(taskImplementation);
if (!Task.class.isAssignableFrom(clazz)) {
throw new IllegalArgumentException("Class " + taskName + " does not implement " + Task.class.getName());
}
Task task = (Task) clazz.newInstance();
Job job = getScheduler().addCustomTaskJob(taskName, task, true, null);
getScheduler().run(job.getName(), "WGA Scheduler Custom Task Runner", options, null);
return job.getName();
}
public boolean importContentStoreDump(ZipInputStream zipIn, WGDatabase targetDB, Logger log) throws IOException, WGAPIException {
return importContentStoreDump(zipIn, targetDB, log, false);
}
public void importContentStoreDump(ZipInputStream zipIn, WGDatabase targetDB) throws IOException, WGAPIException {
importContentStoreDump(zipIn, targetDB, null);
}
public boolean importContentStoreDump(ZipInputStream zipIn, WGDatabase targetDB, Logger log, boolean includeACL) throws IOException, WGAPIException {
return importContentStoreDump(zipIn, targetDB, log, includeACL, false);
}
public boolean importContentStoreDump(ZipInputStream zipIn, WGDatabase targetDB, Logger log, boolean includeACL, boolean includeSystemAreas) throws IOException, WGAPIException {
if (log != null) {
log.info("Extracting dump data");
}
// Create working folder for dump database
File dir = File.createTempFile("csd", ".tmp", WGFactory.getTempDir());
dir.delete();
dir.mkdir();
// Extract dump to folder
ZipEntry entry = zipIn.getNextEntry();
while (entry != null) {
FileOutputStream out = new FileOutputStream(new File(dir, entry.getName()));
WGUtils.inToOut(zipIn, out, 2048);
out.close();
entry = zipIn.getNextEntry();
}
// Open dump database
Map<String, String> options = new HashMap<String, String>();
options.put(WGDatabase.COPTION_MONITORLASTCHANGE, "false");
WGDatabase sourceDB = WGFactory.getInstance().openDatabase(null, de.innovationgate.webgate.api.hsql.WGDatabaseImpl.class.getName(), dir.getAbsolutePath() + "/wgacs", null, null, options);
sourceDB.setDbReference("WGA Content Store Initial data dump");
if (log != null) {
log.info("Importing dump data");
}
// Do the dump
ContentStoreDumpManager importer = new ContentStoreDumpManager(sourceDB, targetDB, log);
boolean result = importer.importDump(includeACL, includeSystemAreas);
// Close dump database
sourceDB.close();
return result;
}
protected static Map<String, String> getDbDefaultAttributes() {
return _dbDefaultAttributes;
}
/**
* stores the given licenses data as wga.skey in config path and do necessary updates on wga.xml to reflect new license file
* @param licenseData
* @throws WGSystemException
*/
/*
public void storeLicenseData(byte[] licenseData) throws WGSystemException {
try {
File licenseFile = new File(configFile.getParentFile(), LICENSE_FILENAME);
if (licenseFile.exists()) {
licenseFile.createNewFile();
}
ByteArrayInputStream bin = new ByteArrayInputStream(licenseData);
FileOutputStream fout = new FileOutputStream(licenseFile);
WGUtils.inToOut(bin, fout, 1024);
fout.close();
log.info("New license data successfully saved in license file '" + licenseFile.getAbsolutePath() + "'.");
// update configuration
updateConfig();
}
catch (Exception e) {
log.error("Unable to store license data.", e);
throw new WGSystemException("Unable to store license data.", e);
}
}*/
private void loadOptions(Map<String, String> thePublisherOptions, Element publisherOptionElements) {
Iterator publisherOptionsIt = publisherOptionElements.elementIterator("option");
while (publisherOptionsIt.hasNext()) {
Element publisherOptionElem = (Element) publisherOptionsIt.next();
try {
thePublisherOptions.put(publisherOptionElem.attributeValue("name"), readOptionValue(publisherOptionElem));
}
catch (IOException e) {
getLog().error("Exception decoding option '" + publisherOptionElem.attributeValue("name") + "'", e);
}
}
}
public void removeCSConfig(WGDatabase database, ContainerInfo info, boolean finalRemove) {
/* This is not safe. The media key may be defined by multiple designs.
Iterator<String> mediaMappings = info.getEnforcedMediaMappings().iterator();
while (mediaMappings.hasNext()) {
String mediaKey = mediaMappings.next();
this.customMediaKeys.remove(mediaKey);
}*/
Iterator<String> elementMappings = info.getEnforcedElementMappings().iterator();
while (elementMappings.hasNext()) {
String elementName = elementMappings.next();
this.customElements.remove(elementName);
}
Iterator<String> encoderMappings = info.getEnforcedEncoderMappings().iterator();
while (encoderMappings.hasNext()) {
String elementName = encoderMappings.next();
_customFormatters.remove(elementName.toLowerCase());
}
Iterator<String> jobDefinitions = info.getEnforcedJobDefinitions().iterator();
while (jobDefinitions.hasNext()) {
String jobName = jobDefinitions.next();
getScheduler().removeJob(jobName);
}
// We only do this if the db is really removed.
// If not, and this is only an info update, the library loader would get updated
// right after this method and we can spare the overhead here
if (finalRemove && info.isEnfordedLibraryUpdate()) {
if (!info.isStaticClasspath() && getLibraryClassLoadingChain().hasSubLoader(info.getDbkey())) {
getLog().info("Removing libraries of database " + info.getDbkey() + " from WGA java library loader");
try {
getLibraryClassLoadingChain().removeSubLoader(info.getDbkey());
}
catch (IllegalStateException e) {
getLog().warn("The libraries of database " + info.getDbkey() + " cannt be removed from WGA java library loader as they are marked static");
}
}
updateLibraryLoader();
}
}
public SystemContainerManager getSystemContainerManager() {
return _systemContainerManager;
}
public boolean logout(String domain, javax.servlet.http.HttpSession session) throws WGAPIException {
// Remove profiles of self-personalized dbs
for (WGDatabase db : getDatabasesForDomain(domain)) {
int persMode = Integer.parseInt((String) readPublisherOptionOrDefault(db, WGACore.DBATTRIB_PERSMODE));
if (persMode == Constants.PERSMODE_LOGIN) {
session.removeAttribute(WGPDispatcher.SESSION_PROFILENAME_INDIVIDUALDB + db.getDbReference());
}
}
// Remove the sessionLogin for this domain
Map<Object, DBLoginInfo> sessionLogins = getSessionLogins(session);
if (domain != null) {
sessionLogins.remove(domain);
}
else {
sessionLogins.clear();
session.removeAttribute("$defaultlogin");
}
return true;
}
public boolean login(String user, String password, String domain, HttpServletRequest request, HttpServletResponse response) throws LoginException, WGAPIException {
// Get the domain configuration
DomainConfiguration domainConfig = getDomainConfig(domain);
if (domainConfig == null) {
throw new LoginException("The domain '" + domain + "' does not exist");
}
// Do login. Either on domain's auth module or on a DB of the domain
boolean isLoginSuccessful = false;
if (domainConfig.getAuthModule() != null) {
// Do a login on the domain's auth module
try {
AuthenticationSession authSession = getBruteForceLoginBlocker().login(domainConfig, user, password);
if (authSession != null) {
isLoginSuccessful = true;
}
}
catch (AuthenticationException e) {
throw new LoginException("Unable to login on domain '" + domain + "'.", e);
}
}
else {
// Find a database of the requested domain
Collection<WGDatabase> dbObjs = getContentdbs().values();
if (dbObjs.isEmpty()) {
return false;
}
Iterator<WGDatabase> dbs = getContentdbs().values().iterator();
WGDatabase db = null;
int accessLevel = WGDatabase.ACCESSLEVEL_NOTLOGGEDIN;
// Do a login on the first database found that belongs to this domain
while (dbs.hasNext()) {
db = dbs.next();
String compareDomain = (String) db.getAttribute(WGACore.DBATTRIB_DOMAIN);
if (compareDomain != null && compareDomain.equalsIgnoreCase(domain)) {
accessLevel = getBruteForceLoginBlocker().login(db, user, password);
if (accessLevel > WGDatabase.ACCESSLEVEL_NOTLOGGEDIN) {
isLoginSuccessful = true;
if (db.isSessionOpen()) {
setSessionCookie(request, response, db);
}
break;
} else {
// unable to login to db of domain
// do not try to login to further dbs in this domain bc.
// - each db of a domain must support the same auth information
// - we will block the login to early bc. each further login request are counted by bruteForceLoginBlocker
isLoginSuccessful = false;
break;
}
}
}
}
// React on login success
if (isLoginSuccessful) {
// First do a logout for sure
logout(domain, request.getSession());
getSessionLogins(request.getSession()).put(domain, new DBLoginInfo(user, password));
// F00004852
// perform a reopenSession on all opened databases of this domain
Iterator<WGDatabase> dbsInDomain = getDatabasesForDomain(domain).iterator();
while (dbsInDomain.hasNext()) {
WGDatabase db = dbsInDomain.next();
if (db.isSessionOpen()) {
db.reopenSession(user, password);
}
}
return true;
} else {
return false;
}
}
protected void setSessionCookie(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, WGDatabase database) {
try {
if (!database.getSessionContext().isAnonymous() && database.hasFeature(WGDatabase.FEATURE_SESSIONTOKEN)) {
String cookieName = (String) database.getAttribute(WGACore.DBATTRIB_SESSIONCOOKIE);
String sessionToken = database.getSessionContext().getSessionToken();
if (cookieName != null && sessionToken != null && !sessionToken.equals(request.getSession().getAttribute(WGACore.SESSION_COOKIESET + cookieName))) {
Cookie sessionCookie = new Cookie(cookieName, sessionToken);
sessionCookie.setPath("/");
String sessionCookieDomain = (String) database.getAttribute(WGACore.DBATTRIB_SESSIONCOOKIEDOMAIN);
if (sessionCookieDomain != null) {
sessionCookie.setDomain(sessionCookieDomain);
}
else {
sessionCookie.setDomain(getSecondLevelDomain(request.getServerName()));
}
response.addCookie(sessionCookie);
request.getSession().setAttribute(WGACore.SESSION_COOKIESET + cookieName, sessionToken);
}
}
}
catch (WGBackendException e) {
getLog().error("Error setting session cookie", e);
}
}
private String getSecondLevelDomain(String serverName) {
int noOfPoints = WGUtils.countOccurences(serverName, ".");
// If we have less than three parts we cannot cutoff subdomains
if (noOfPoints < 2) {
return serverName;
}
int tldPos = serverName.lastIndexOf(".");
int sldPos = serverName.lastIndexOf(".", tldPos - 1);
return serverName.substring(sldPos);
}
public void disconnectPlugin(WGAPlugin plugin) {
String dbKey = plugin.buildDatabaseKey();
WGDatabase db = this.contentdbs.get(dbKey);
if (db != null) {
getLog().info("Disconnecting plugin " + plugin.getPluginID().getUniqueName() + " Version " + plugin.getPluginID().getVersion().toString());
removeContentDB(dbKey);
}
}
public WGAPluginSet getPluginSet() {
return pluginSet;
}
public File getWgaDataDir() {
return _wgaDataDir;
}
public List<WGAFilterConfig> getFilterMappings() {
return filterMappings;
}
public TMLScriptGlobalRegistry getTmlscriptGlobalRegistry() {
return _tmlscriptGlobalRegistry;
}
public int getDefaultPort(WGDatabase db, String protocol) {
// Retrieve from publisher option
String strProtocol = (String) db.getAttribute(DBATTRIB_DEFAULTPORT_BASE + protocol.toUpperCase());
if (strProtocol != null) {
try {
int port = Integer.parseInt(strProtocol);
return port;
}
catch (NumberFormatException e) {
getLog().error("Default port of '" + protocol + "' for database '" + db.getDbReference() + "' not numeric: " + strProtocol);
}
}
// Unconfigured default ports
if (protocol.equalsIgnoreCase("http")) {
return 80;
}
else if (protocol.equalsIgnoreCase("https")) {
return 443;
}
return 80;
}
/*
public ResourceConfiguration getResourceConfiguration() {
return _resourceConfiguration;
}*/
/**
* retrieves the global wga mail configuration
* might be null if not configured in detail mailhost is not set in wgaxml
* @return
*/
public WGAMailConfiguration getMailConfig() {
return _mailConfig;
}
public void send(WGAMailNotification notification) {
WGAMailConfiguration config = getMailConfig();
if (config != null && config.isEnableAdminNotifications()) {
try {
Message msg = new MimeMessage(config.createMailSession());
// set recipient and from address
String toAddress = config.getToAddress();
if (toAddress == null) {
getLog().error("Unable to send wga admin notification because no recipient address is configured");
return;
}
msg.setRecipient(Message.RecipientType.TO, new InternetAddress(toAddress));
InternetAddress[] fromAddr = new InternetAddress[1];
fromAddr[0] = new InternetAddress(config.getFromAddress());
msg.addFrom(fromAddr);
msg.setSentDate(new Date());
msg.setSubject(notification.getSubject());
msg.setHeader(WGAMailNotification.HEADERFIELD_TYPE, notification.getType());
MimeMultipart content = new MimeMultipart();
MimeBodyPart body = new MimeBodyPart();
StringBuffer strBody = new StringBuffer();
strBody.append("<html><head></head><body>");
strBody.append(notification.getMessage());
String rootURL = getWgaConfiguration().getRootURL();
if (rootURL != null) {
strBody.append("<br><br>");
strBody.append("<a href=\"" + rootURL + "/plugin-admin\">Open OpenWGA admin client</a><br>");
}
// append footer
InetAddress localMachine = InetAddress.getLocalHost();
String hostname = localMachine.getHostName();
strBody.append("<br><br><b>System information:</b><br>");
strBody.append("<b>WGA Publisher Version:</b> " + WGACore.getReleaseString() + "<br>");
strBody.append("<b>Hostname:</b> " + hostname + "<br>");
strBody.append("<b>Operation System:</b> " + System.getProperty("os.name") + " Version " + System.getProperty("os.version") + " (" + System.getProperty("os.arch") + ")<br>");
strBody.append("<b>Java virtual machine:</b> " + System.getProperty("java.vm.name") + " Version " + System.getProperty("java.vm.version") + " (" + System.getProperty("java.vm.vendor") + ")");
strBody.append("</body></html>");
body.setText(strBody.toString());
body.setHeader( "MIME-Version" , "1.0" );
body.setHeader( "Content-Type" , "text/html");
content.addBodyPart( body );
if (notification.isAttachLogfile()) {
MimeBodyPart attachmentBody = new MimeBodyPart();
StringWriter applog = new StringWriter();
int applogSize = getApplogLines();
int offset = applogSize - notification.getLogfileLines();
if (offset < 0) {
offset = 1;
}
writeApplogContent(offset, notification.getLogfileLines(), applog, LogLevel.LEVEL_INFO, false);
attachmentBody.setDataHandler(new DataHandler(applog.toString(), "text/plain"));
attachmentBody.setFileName("wga.log");
content.addBodyPart(attachmentBody);
}
msg.setContent(content);
// Send mail
Thread mailThread = new Thread(new AsyncMailSender(msg), "WGAMailSender");
mailThread.start();
} catch (Exception e) {
getLog().error("Unable to send wga admin notification.", e);
}
}
}
private class AsyncMailSender implements Runnable {
private Message _message;
public AsyncMailSender(Message message) {
_message = message;
}
public void run() {
try {
Transport.send(_message);
} catch (MessagingException e) {
getLog().error("Unable to send wga notification email.", e);
}
}
}
public File getLoggingDir() {
return loggingDir;
}
public static List<WGLanguage> getLanguageDefinitions(WGDatabase database, Collection langKeys) throws WGAPIException {
List<WGLanguage> langs = new ArrayList<WGLanguage>();
Iterator keys = langKeys.iterator();
while (keys.hasNext()) {
String key = (String) keys.next();
WGLanguage lang = database.getLanguage(key);
if (lang != null) {
langs.add(lang);
}
}
return langs;
}
public int getStatus() {
return _status;
}
public WGAConfiguration getWgaConfiguration() {
return _wgaConfiguration;
}
public String getErrorPage() {
return _errorPage;
}
public WGADesignManager getDesignManager() {
return _designManager;
}
public void logCategoryInfo(String msg, int level) {
WGUtils.logCategoryInfo(getLog(), msg, level);
}
public Cache getDesignFileCache() {
return designFileCache;
}
public void saveWgaConfiguration(final WGAConfiguration config) throws FileNotFoundException, Exception {
// Everything done in a separate thread
// updateConfig() will close database sessions and we need synchronisation on the whole block
Runnable updateConfigTask = new Runnable() {
public void run() {
synchronized (WGACore.this) {
try {
// Replace WGA Configuration object
_wgaConfiguration = config;
// First write to buffer, so serialisation/validation errors are catched before it is actually written to disk
ByteArrayOutputStream buffOut = new ByteArrayOutputStream();
WGAConfiguration.write(getWgaConfiguration(), buffOut);
// Write buffered output to file
FileOutputStream configOut = new FileOutputStream(configFile);
configOut.write(buffOut.toByteArray());
configOut.flush();
configOut.close();
// enforce configuratioe
updateConfig();
}
catch (ConfigValidationException e) {
getLog().error("Configuration update failed because of validation errors:");
Iterator<ValidationError> errors = e.getValidationErrors().iterator();
while (errors.hasNext()) {
ValidationError validationError = (ValidationError) errors.next();
getLog().error(validationError.getMessage());
}
}
catch (Exception e) {
getLog().error("Exception updating configuration", e);
}
}
}
};
Thread updateConfigThread = new Thread(updateConfigTask);
updateConfigThread.start();
updateConfigThread.join();
}
public WGAConfiguration cloneWgaConfiguration() {
return (WGAConfiguration) XStreamUtils.clone(_wgaConfiguration);
}
public void setFilter(WGAFilter filter) {
_filter = filter;
}
public WGAFilter getFilter() {
return _filter;
}
public Map<String, WGDatabaseServer> getDatabaseServers() {
return _databaseServers;
}
public List<String> getEncodingFormatterNames() {
List<String> formatters = new ArrayList<String>();
formatters.addAll(_customFormatters.keySet());
formatters.addAll(_systemFormatters.keySet());
// Embedded system formatters - that are served from outside the formatters registry
formatters.add(ENCODER_CRLF);
formatters.add(ENCODER_HTML);
formatters.add(ENCODER_RTF);
formatters.add(ENCODER_RTFSYSTEM);
formatters.add(ENCODER_XML);
formatters.add(ENCODER_NONE);
return formatters;
}
public WebTMLCache getWebTMLCache() {
return _webTMLCache;
}
public Map getDomainConfigs() {
return domainConfigs;
}
public static DynamicClassLoadingChain getLibraryClassLoadingChain() {
return libraryClassLoadingChain;
}
public WGALoggerWrapper getAccessLogger() {
return _accessLogger;
}
public void setProfilingEnabled(boolean profilingEnabled) {
this.profilingEnabled = profilingEnabled;
}
public Map<String, ShareDefinition> getShares() {
return _shares;
}
public void addCustomShare(ShareDefinition def) throws ShareInitException {
def.setOrigin(ShareDefinition.ORIGIN_CUSTOM);
getShares().put(def.getName(), def);
getLog().info("Added custom share '" + def.getName() + "'");
}
public Object readPublisherOptionOrDefault(WGDatabase db, String name) {
// Fetch option definition
OptionDefinition optionDef = null;
Class typeClass = ContentDatabasePublisherOptionsModuleType.class;
Class collectorClass = ContentDatabasePublisherOptionsCollector.class;
if (db.hasFeature(WGDatabase.FEATURE_FULLCONTENTFEATURES)) {
typeClass = ContentStorePublisherOptionsModuleType.class;
collectorClass = ContentStorePublisherOptionsCollector.class;
}
if (getModuleRegistry() != null) {
ModuleDefinition pOptionDefs = getModuleRegistry().getModuleDefinition(typeClass, collectorClass);
optionDef = pOptionDefs.getOptionDefinitions().get(name);
}
// Read the option value, default it if neccessary
Object value = db.getAttribute(name);
if (value == null && optionDef != null && optionDef.getDefaultValue() != null) {
value = optionDef.getDefaultValue();
}
if (optionDef != null) {
try {
return OptionReader.unconvertOptionValue(optionDef, value);
}
catch (Exception e) {
throw new RuntimeException("Exception unconverting publisher option '" + name + "' with value '" + value + "' on database '" + db.getDbReference() + "'", e);
}
}
else {
return value;
}
}
public WGAURLBuilder retrieveURLBuilder(HttpServletRequest request, WGDatabase db) {
WGAURLBuilder builder = (WGAURLBuilder) request.getAttribute(WGACore.ATTRIB_URLBUILDER);
if (builder == null) {
// Look if the builder to use is predefined by DB attribute
Object urlBuilderClassName = db.getAttribute(WGACore.DBATTRIB_URLBUILDER);
if (urlBuilderClassName != null && urlBuilderClassName instanceof String) {
try {
Class builderClazz = WGACore.getLibraryLoader().loadClass((String)urlBuilderClassName);
builder = (WGAURLBuilder) builderClazz.newInstance();
} catch (Exception e) {
getLog().error("Unable to instatiate url builder '" + urlBuilderClassName + "'. Using default url builder.", e);
}
}
// Default/Fallback URL builder for normal web pages
if (builder == null) {
DefaultURLBuilder defBuilder = new DefaultURLBuilder();
if ("true".equals(request.getParameter("forceClassicURL"))) {
defBuilder.setTitlePathAllowed(false);
}
builder = defBuilder;
}
request.setAttribute(WGACore.ATTRIB_URLBUILDER, builder);
}
return builder;
}
public List<HTMLHeadInclusion> getHtmlHeadInclusions() {
return _htmlHeadInclusions;
}
public void setDefaultAnalyzer(Analyzer defaultAnalyzer) {
this.defaultAnalyzer = defaultAnalyzer;
}
public String getClassLocation(String className) {
return WGUtils.which(className, getLibraryLoader());
}
}