Index: portal-ejb/src/com/liferay/portal/cms/servlet/CMSServlet.java
===================================================================
--- portal-ejb/src/com/liferay/portal/cms/servlet/CMSServlet.java	(revision 6221)
+++ portal-ejb/src/com/liferay/portal/cms/servlet/CMSServlet.java	(working copy)
@@ -34,6 +34,7 @@
 import com.liferay.portal.util.PortalUtil;
 import com.liferay.portal.util.PrefsPropsUtil;
 import com.liferay.portal.util.PropsUtil;
+import com.liferay.portal.util.VirtualHostingUtil;
 import com.liferay.util.ExtPropertiesLoader;
 import com.liferay.util.GetterUtil;
 import com.liferay.util.ParamUtil;
@@ -59,7 +60,7 @@
  *
  * @author Brian Wing Shun Chan
  * @author Jorge Ferrer
- * @author Raymond Augé
+ * @author Raymond Augï¿½
  *
  */
 public class CMSServlet extends HttpServlet {
@@ -150,6 +151,8 @@
 
 		ThemeDisplay themeDisplay = null;
 
+		long _companyId = VirtualHostingUtil.getCompanyId(req);
+		
 		try {
 			themeDisplay = ThemeDisplayFactory.create();
 
Index: portal-ejb/src/com/liferay/portal/servlet/filters/autologin/AutoLoginFilter.java
===================================================================
--- portal-ejb/src/com/liferay/portal/servlet/filters/autologin/AutoLoginFilter.java	(revision 6221)
+++ portal-ejb/src/com/liferay/portal/servlet/filters/autologin/AutoLoginFilter.java	(working copy)
@@ -30,6 +30,7 @@
 import com.liferay.portal.security.pwd.PwdEncryptor;
 import com.liferay.portal.util.PortalUtil;
 import com.liferay.portal.util.PropsUtil;
+import com.liferay.portal.util.VirtualHostingUtil;
 import com.liferay.portal.util.WebKeys;
 import com.liferay.util.GetterUtil;
 import com.liferay.util.InstancePool;
@@ -91,6 +92,8 @@
 		String remoteUser = httpReq.getRemoteUser();
 		String jUserName = (String)ses.getAttribute("j_username");
 
+		long _companyId = VirtualHostingUtil.getCompanyId(req);
+		
 		if ((remoteUser == null) && (jUserName == null)) {
 			req.setAttribute(WebKeys.COMPANY_ID, new Long(_companyId));
 
Index: portal-ejb/src/com/liferay/portal/servlet/filters/layoutcache/LayoutCacheFilter.java
===================================================================
--- portal-ejb/src/com/liferay/portal/servlet/filters/layoutcache/LayoutCacheFilter.java	(revision 6221)
+++ portal-ejb/src/com/liferay/portal/servlet/filters/layoutcache/LayoutCacheFilter.java	(working copy)
@@ -38,6 +38,7 @@
 import com.liferay.portal.service.PortletLocalServiceUtil;
 import com.liferay.portal.util.PortalUtil;
 import com.liferay.portal.util.PropsUtil;
+import com.liferay.portal.util.VirtualHostingUtil;
 import com.liferay.util.BrowserSniffer;
 import com.liferay.util.GetterUtil;
 import com.liferay.util.ParamUtil;
@@ -129,6 +130,8 @@
 
 			String key = getCacheKey(httpReq);
 
+			long _companyId = VirtualHostingUtil.getCompanyId(req);
+			
 			CacheResponseData data =
 				LayoutCacheUtil.getCacheResponseData(_companyId, key);
 
@@ -216,7 +219,7 @@
 		return sm.toString().trim().toUpperCase();
 	}
 
-	protected String getPlid(
+	protected String getPlid(long _companyId,
 		String pathInfo, String servletPath, String defaultPlid) {
 
 		if (_pattern == _PATTERN_LAYOUT) {
@@ -321,9 +324,9 @@
 		if (_pattern == _PATTERN_RESOURCE) {
 			return true;
 		}
-
+		long _companyId = VirtualHostingUtil.getCompanyId(req);
 		try {
-			String plid = getPlid(
+			String plid = getPlid(_companyId, 
 				req.getPathInfo(), req.getServletPath(),
 				ParamUtil.getString(req, "p_l_id"));
 
Index: portal-ejb/src/com/liferay/portal/servlet/filters/virtualhost/VirtualHostFilter.java
===================================================================
--- portal-ejb/src/com/liferay/portal/servlet/filters/virtualhost/VirtualHostFilter.java	(revision 6221)
+++ portal-ejb/src/com/liferay/portal/servlet/filters/virtualhost/VirtualHostFilter.java	(working copy)
@@ -38,6 +38,7 @@
 import com.liferay.portal.servlet.MainServlet;
 import com.liferay.portal.util.ContentUtil;
 import com.liferay.portal.util.PortalUtil;
+import com.liferay.portal.util.VirtualHostingUtil;
 import com.liferay.util.GetterUtil;
 import com.liferay.util.SetUtil;
 import com.liferay.util.StringUtil;
@@ -137,12 +138,14 @@
 			String host = PortalUtil.getHost(httpReq);
 			String mainPath = MainServlet.DEFAULT_MAIN_PATH;
 
+			long _companyId = VirtualHostingUtil.getCompanyId(req);
+			
 			if (_log.isDebugEnabled()) {
 				_log.debug("Host " + host);
 			}
 
 			try {
-				if (isValidHost(host)) {
+				if (isValidHost(_companyId, host)) {
 					LayoutSet layoutSet =
 						LayoutSetLocalServiceUtil.getLayoutSet(
 							_companyId, host);
@@ -199,7 +202,7 @@
 		return true;
 	}
 
-	protected boolean isValidHost(String host)
+	protected boolean isValidHost(long companyId, String host)
 		throws PortalException, SystemException {
 
 		if (Validator.isNotNull(host)) {
@@ -208,7 +211,7 @@
 			}
 
 			Company company = CompanyLocalServiceUtil.getCompanyById(
-				_companyId);
+				companyId);
 
 			if (company.getPortalURL().indexOf(host) == -1) {
 				return true;
Index: portal-ejb/src/com/liferay/portal/servlet/FriendlyURLServlet.java
===================================================================
--- portal-ejb/src/com/liferay/portal/servlet/FriendlyURLServlet.java	(revision 6221)
+++ portal-ejb/src/com/liferay/portal/servlet/FriendlyURLServlet.java	(working copy)
@@ -34,6 +34,7 @@
 import com.liferay.portal.util.PortalInstances;
 import com.liferay.portal.util.PortalUtil;
 import com.liferay.portal.util.PropsUtil;
+import com.liferay.portal.util.VirtualHostingUtil;
 import com.liferay.portal.util.WebKeys;
 import com.liferay.util.GetterUtil;
 import com.liferay.util.Validator;
@@ -110,7 +111,7 @@
 		String redirect = mainPath;
 
 		try {
-			redirect = getRedirect(
+			redirect = getRedirect(req, 
 				req.getPathInfo(), mainPath, req.getParameterMap());
 
 			LastPath lastPath = new LastPath(
@@ -150,7 +151,7 @@
 		return _companyId;
 	}
 
-	protected String getRedirect(String path, String mainPath, Map params)
+	protected String getRedirect(HttpServletRequest req, String path, String mainPath, Map params)
 		throws Exception {
 
 		if (Validator.isNull(path)) {
@@ -184,6 +185,7 @@
 
 		Group group = null;
 
+		long _companyId = VirtualHostingUtil.getCompanyId(req);
 		try {
 			group = GroupLocalServiceUtil.getFriendlyURLGroup(
 				_companyId, friendlyURL);
Index: portal-ejb/src/com/liferay/portal/servlet/ImageServlet.java
===================================================================
--- portal-ejb/src/com/liferay/portal/servlet/ImageServlet.java	(revision 6221)
+++ portal-ejb/src/com/liferay/portal/servlet/ImageServlet.java	(working copy)
@@ -28,6 +28,7 @@
 import com.liferay.portal.service.impl.ImageLocalUtil;
 import com.liferay.portal.util.PortalInstances;
 import com.liferay.portal.util.PortalUtil;
+import com.liferay.portal.util.VirtualHostingUtil;
 import com.liferay.util.HttpHeaders;
 import com.liferay.util.ParamUtil;
 import com.liferay.util.Validator;
@@ -115,7 +116,8 @@
 
 	protected String getImageId(HttpServletRequest req) {
 		String path = req.getPathInfo();
-
+		long _companyId = VirtualHostingUtil.getCompanyId(req);
+		
 		// The image id may be passed in as image_id, img_id, or i_id
 
 		String imageId = ParamUtil.getString(req, "image_id");
Index: portal-ejb/src/com/liferay/portal/servlet/LuceneServlet.java
===================================================================
--- portal-ejb/src/com/liferay/portal/servlet/LuceneServlet.java	(revision 6221)
+++ portal-ejb/src/com/liferay/portal/servlet/LuceneServlet.java	(working copy)
@@ -29,9 +29,12 @@
 import com.liferay.portal.lucene.LuceneUtil;
 import com.liferay.portal.util.PortalUtil;
 import com.liferay.portal.util.PropsUtil;
+import com.liferay.portal.util.VirtualHostingUtil;
 import com.liferay.util.GetterUtil;
 
 import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
 
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletContext;
@@ -47,10 +50,10 @@
 
 /**
  * <a href="LuceneServlet.java.html"><b><i>View Source</i></b></a>
- *
+ * 
  * @author Brian Wing Shun Chan
  * @author Jorge Ferrer
- *
+ * 
  */
 public class LuceneServlet extends HttpServlet {
 
@@ -62,93 +65,108 @@
 
 			_companyId = PortalUtil.getCompanyIdByWebId(ctx);
 
-			if (GetterUtil.getBoolean(
-					PropsUtil.get(PropsUtil.INDEX_ON_STARTUP))) {
+			initCompany(_companyId);
+	
+			VirtualHostingUtil.setLuceneServlet(this);
+			String[] otherIds = VirtualHostingUtil.getCompanyIds();
 
-				_indexer = new LuceneIndexer(_companyId);
+			for (int i = 0; i < otherIds.length; i++) {
+				initCompany(PortalUtil.getCompanyIdByWebId(otherIds[i]));
+			}
+		}
+	}
 
-				if (GetterUtil.getBoolean(
-						PropsUtil.get(PropsUtil.INDEX_WITH_THREAD)) ||
-					ServerDetector.isOrion()) {
+	public void initCompany(long _companyId) {
+		LuceneIndexer _indexer = null;
+		Thread _indexerThread = null;
 
-					_indexerThread = new Thread(
-						_indexer, THREAD_NAME + "." + _companyId);
+		if (GetterUtil.getBoolean(PropsUtil.get(PropsUtil.INDEX_ON_STARTUP))) {
 
-					_indexerThread.setPriority(THREAD_PRIORITY);
-					_indexerThread.start();
-				}
-				else {
-					_indexer.reIndex();
-				}
+			_indexer = new LuceneIndexer(_companyId);
+			_indexers.put(new Long(_companyId), _indexer);
+
+			if (GetterUtil.getBoolean(PropsUtil
+					.get(PropsUtil.INDEX_WITH_THREAD))
+					|| ServerDetector.isOrion()) {
+
+				_indexerThread = new Thread(_indexer, THREAD_NAME + "."
+						+ _companyId);
+
+				_indexerThread.setPriority(THREAD_PRIORITY);
+				_indexerThread.start();
+				_indexerThreads.put(new Long(_companyId), _indexerThread);
+			} else {
+				_indexer.reIndex();
 			}
-			else {
-				Directory luceneDir = LuceneUtil.getLuceneDir(_companyId);
+		} else {
+			Directory luceneDir = LuceneUtil.getLuceneDir(_companyId);
 
-				IndexWriter writer = null;
+			IndexWriter writer = null;
 
-				// Lucene does not properly release its lock on the index when
-				// IndexWriter throws an exception
+			// Lucene does not properly release its lock on the index when
+			// IndexWriter throws an exception
 
-				try {
-					if (luceneDir.fileExists("segments")) {
-						writer = new IndexWriter(
-							luceneDir, LuceneUtil.getAnalyzer(), false);
-					}
-					else {
-						writer = new IndexWriter(
-							luceneDir, LuceneUtil.getAnalyzer(), true);
-					}
+			try {
+				if (luceneDir.fileExists("segments")) {
+					writer = new IndexWriter(luceneDir, LuceneUtil
+							.getAnalyzer(), false);
+				} else {
+					writer = new IndexWriter(luceneDir, LuceneUtil
+							.getAnalyzer(), true);
 				}
-				catch (IOException ioe) {
-					_log.error(ioe);
-				}
-				finally {
-					if (writer != null) {
-						try {
-							writer.close();
-						}
-						catch (IOException ioe) {
-							_log.error(ioe);
-						}
+			} catch (IOException ioe) {
+				_log.error(ioe);
+			} finally {
+				if (writer != null) {
+					try {
+						writer.close();
+					} catch (IOException ioe) {
+						_log.error(ioe);
 					}
 				}
 			}
+		}
 
-			if (GetterUtil.getBoolean(
-					PropsUtil.get(PropsUtil.LUCENE_STORE_JDBC_AUTO_CLEAN_UP))) {
+		if (GetterUtil.getBoolean(PropsUtil
+				.get(PropsUtil.LUCENE_STORE_JDBC_AUTO_CLEAN_UP))) {
 
-				try {
-					JobScheduler.schedule(new CleanUpJob());
-				}
-				catch (SchedulerException se) {
-					_log.error(se);
-				}
+			try {
+				JobScheduler.schedule(new CleanUpJob());
+			} catch (SchedulerException se) {
+				_log.error(se);
 			}
 		}
+
 	}
 
 	public void destroy() {
 
 		// Wait for indexer to be gracefully interrupted
 
-		if ((_indexer != null) && (!_indexer.isFinished()) &&
-			(_indexerThread != null)) {
+		destroyCompany(_companyId);
 
+		// Parent
+
+		super.destroy();
+	}
+	
+	public void destroyCompany(long companyId) {
+		final Long key = new Long(companyId);
+		LuceneIndexer _indexer = (LuceneIndexer)_indexers.get(key);
+		Thread _indexerThread = (Thread)_indexerThreads.get(key);
+		if ((_indexer != null) && (!_indexer.isFinished())
+				&& (_indexerThread != null)) {
+
 			_log.warn("Waiting for Lucene indexer to shutdown");
 
 			_indexer.halt();
 
 			try {
 				_indexerThread.join(THREAD_TIMEOUT);
-			}
-			catch (InterruptedException e) {
+			} catch (InterruptedException e) {
 				_log.error("Lucene indexer shutdown interrupted", e);
 			}
-		}
-
-		// Parent
-
-		super.destroy();
+		}		
 	}
 
 	private static final String THREAD_NAME = LuceneIndexer.class.getName();
@@ -160,7 +178,13 @@
 	private static Log _log = LogFactory.getLog(LuceneServlet.class);
 
 	private long _companyId;
-	private LuceneIndexer _indexer;
-	private Thread _indexerThread;
 
+	//private LuceneIndexer _indexer;
+
+	//private Thread _indexerThread;
+
+	private Map _indexers = new HashMap();
+
+	private Map _indexerThreads = new HashMap();
+
 }
\ No newline at end of file
Index: portal-ejb/src/com/liferay/portal/servlet/MainServlet.java
===================================================================
--- portal-ejb/src/com/liferay/portal/servlet/MainServlet.java	(revision 6221)
+++ portal-ejb/src/com/liferay/portal/servlet/MainServlet.java	(working copy)
@@ -57,6 +57,7 @@
 import com.liferay.portal.util.ReleaseInfo;
 import com.liferay.portal.util.SAXReaderFactory;
 import com.liferay.portal.util.ShutdownUtil;
+import com.liferay.portal.util.VirtualHostingUtil;
 import com.liferay.portal.util.WebAppPool;
 import com.liferay.portal.util.WebKeys;
 import com.liferay.portal.velocity.VelocityContextPool;
@@ -144,7 +145,6 @@
 			catch (Exception e) {
 				_log.error(e, e);
 			}
-
 			ServletContext ctx = getServletContext();
 
 			String servletContextName = GetterUtil.getString(
@@ -224,60 +224,6 @@
 				_log.error(e, e);
 			}
 
-			// Company id
-
-			if (_log.isDebugEnabled()) {
-				_log.debug("Company id");
-			}
-
-			String webId = GetterUtil.getString(
-				ctx.getInitParameter("company_web_id"));
-
-			try {
-				Company company = CompanyLocalServiceUtil.checkCompany(webId);
-
-				_companyId = company.getCompanyId();
-				_companyIdString = String.valueOf(_companyId);
-			}
-			catch (Exception e) {
-				_log.error(e, e);
-			}
-
-			ctx.setAttribute(WebKeys.COMPANY_ID, new Long(_companyId));
-
-			CompanyThreadLocal.setCompanyId(_companyId);
-
-			// Initialize display
-
-			if (_log.isDebugEnabled()) {
-				_log.debug("Initialize display");
-			}
-
-			try {
-				String xml = Http.URLtoString(ctx.getResource(
-					"/WEB-INF/liferay-display.xml"));
-
-				PortletCategory portletCategory =
-					(PortletCategory)WebAppPool.get(
-						_companyIdString, WebKeys.PORTLET_CATEGORY);
-
-				if (portletCategory == null) {
-					portletCategory = new PortletCategory();
-				}
-
-				PortletCategory newPortletCategory =
-					PortletLocalServiceUtil.getEARDisplay(xml);
-
-				portletCategory.merge(newPortletCategory);
-
-				WebAppPool.put(
-					_companyIdString, WebKeys.PORTLET_CATEGORY,
-					portletCategory);
-			}
-			catch (Exception e) {
-				_log.error(e, e);
-			}
-
 			// Initialize layout templates
 
 			if (_log.isDebugEnabled()) {
@@ -318,26 +264,9 @@
 			}
 			catch (Exception e) {
 				_log.error(e, e);
-			}
+			}			
 
-			// Check journal content search
 
-			if (_log.isDebugEnabled()) {
-				_log.debug("Check journal content search");
-			}
-
-			if (GetterUtil.getBoolean(PropsUtil.get(
-					0, PropsUtil.JOURNAL_SYNC_CONTENT_SEARCH_ON_STARTUP))) {
-
-				try {
-					JournalContentSearchLocalServiceUtil.checkContentSearches(
-						_companyId);
-				}
-				catch (Exception e) {
-					_log.error(e, e);
-				}
-			}
-
 			// Check web settings
 
 			if (_log.isDebugEnabled()) {
@@ -353,136 +282,233 @@
 			catch (Exception e) {
 				_log.error(e, e);
 			}
+			
+			
+			// Company id
 
-			// Scheduler
-
 			if (_log.isDebugEnabled()) {
-				_log.debug("Scheduler");
+				_log.debug("Company id");
 			}
 
-			try {
-				Iterator itr = PortletLocalServiceUtil.getPortlets(
-					_companyId).iterator();
+			String webId = GetterUtil.getString(
+				ctx.getInitParameter("company_web_id"));	
+			
+			initCompany(webId, true);
+			
+			VirtualHostingUtil.init(_companyId, _companyIdString, this);
+			String []otherIds = VirtualHostingUtil.getCompanyIds();
+			for (int i=0;i<otherIds.length;i++) {
+				initCompany(otherIds[i], false);
+			}	
+		}
+	}
+		
+		
+	public void initCompany(String webId, boolean defaultCompany) {
 
-				while (itr.hasNext()) {
-					Portlet portlet = (Portlet)itr.next();
+		ServletContext ctx = getServletContext();
+		
+		// Override global
+		long _companyId = -1;
+		String _companyIdString = null;
+		
+		try {
+			Company company = CompanyLocalServiceUtil.checkCompany(webId);
 
-					String className = portlet.getSchedulerClass();
+			_companyId = company.getCompanyId();
+			_companyIdString = String.valueOf(_companyId);
+		}
+		catch (Exception e) {
+			_log.error(e, e);
+		}
 
-					if (portlet.isActive() && Validator.isNotNull(className)) {
-						Scheduler scheduler =
-							(Scheduler)InstancePool.get(className);
+		if (defaultCompany) {
+			ctx.setAttribute(WebKeys.COMPANY_ID, new Long(_companyId));
+			this._companyId = _companyId;
+			this._companyIdString = _companyIdString;
+		}
+		
+		CompanyThreadLocal.setCompanyId(_companyId);
 
-						scheduler.schedule();
-					}
-				}
+		// Initialize display
+
+		if (_log.isDebugEnabled()) {
+			_log.debug("Initialize display");
+		}
+
+		try {
+			String xml = Http.URLtoString(ctx.getResource(
+				"/WEB-INF/liferay-display.xml"));
+
+			PortletCategory portletCategory =
+				(PortletCategory)WebAppPool.get(
+					_companyIdString, WebKeys.PORTLET_CATEGORY);
+
+			if (portletCategory == null) {
+				portletCategory = new PortletCategory();
 			}
-			catch (ObjectAlreadyExistsException oaee) {
+
+			PortletCategory newPortletCategory =
+				PortletLocalServiceUtil.getEARDisplay(xml);
+
+			portletCategory.merge(newPortletCategory);
+
+			WebAppPool.put(
+				_companyIdString, WebKeys.PORTLET_CATEGORY,
+				portletCategory);
+		}
+		catch (Exception e) {
+			_log.error(e, e);
+		}
+
+		// Check journal content search
+
+		if (_log.isDebugEnabled()) {
+			_log.debug("Check journal content search");
+		}
+
+		if (GetterUtil.getBoolean(PropsUtil.get(
+				0, PropsUtil.JOURNAL_SYNC_CONTENT_SEARCH_ON_STARTUP))) {
+
+			try {
+				JournalContentSearchLocalServiceUtil.checkContentSearches(
+					_companyId);
 			}
 			catch (Exception e) {
 				_log.error(e, e);
 			}
+		}
 
-			// SMTP message listener
+		// Scheduler
 
-			if (_log.isDebugEnabled()) {
-				_log.debug("SMTP message listener");
-			}
+		if (_log.isDebugEnabled()) {
+			_log.debug("Scheduler");
+		}
 
-			try {
-				Iterator itr = PortletLocalServiceUtil.getPortlets(
-					_companyId).iterator();
+		try {
+			Iterator itr = PortletLocalServiceUtil.getPortlets(
+				_companyId).iterator();
 
-				while (itr.hasNext()) {
-					Portlet portlet = (Portlet)itr.next();
+			while (itr.hasNext()) {
+				Portlet portlet = (Portlet)itr.next();
 
-					MessageListener smtpMessageListener =
-						portlet.getSmtpMessageListener();
+				String className = portlet.getSchedulerClass();
 
-					if (portlet.isActive() && (smtpMessageListener != null)) {
-						SMTPServerUtil.addListener(smtpMessageListener);
-					}
+				if (portlet.isActive() && Validator.isNotNull(className)) {
+					Scheduler scheduler =
+						(Scheduler)InstancePool.get(className);
+
+					scheduler.schedule();
 				}
 			}
-			catch (ObjectAlreadyExistsException oaee) {
-			}
-			catch (Exception e) {
-				_log.error(e, e);
-			}
+		}
+		catch (ObjectAlreadyExistsException oaee) {
+		}
+		catch (Exception e) {
+			_log.error(e, e);
+		}
 
-			// LDAP Import
+		// SMTP message listener
 
-			try {
-				if (PortalLDAPUtil.isImportOnStartup(_companyId)) {
-					PortalLDAPUtil.importFromLDAP(_companyId);
+		if (_log.isDebugEnabled()) {
+			_log.debug("SMTP message listener");
+		}
+
+		try {
+			Iterator itr = PortletLocalServiceUtil.getPortlets(
+				_companyId).iterator();
+
+			while (itr.hasNext()) {
+				Portlet portlet = (Portlet)itr.next();
+
+				MessageListener smtpMessageListener =
+					portlet.getSmtpMessageListener();
+
+				if (portlet.isActive() && (smtpMessageListener != null)) {
+					SMTPServerUtil.addListener(smtpMessageListener);
 				}
 			}
-			catch (Exception e){
-				_log.error(e, e);
-			}
+		}
+		catch (ObjectAlreadyExistsException oaee) {
+		}
+		catch (Exception e) {
+			_log.error(e, e);
+		}
 
-			// Message resources
+		// LDAP Import
 
-			if (_log.isDebugEnabled()) {
-				_log.debug("Message resources");
+		try {
+			if (PortalLDAPUtil.isImportOnStartup(_companyId)) {
+				PortalLDAPUtil.importFromLDAP(_companyId);
 			}
+		}
+		catch (Exception e){
+			_log.error(e, e);
+		}
 
-			MultiMessageResources messageResources =
-				(MultiMessageResources)ctx.getAttribute(Globals.MESSAGES_KEY);
+		// Message resources
 
-			messageResources.setServletContext(ctx);
+		if (_log.isDebugEnabled()) {
+			_log.debug("Message resources");
+		}
 
-			WebAppPool.put(
-				_companyIdString, Globals.MESSAGES_KEY, messageResources);
+		MultiMessageResources messageResources =
+			(MultiMessageResources)ctx.getAttribute(Globals.MESSAGES_KEY);
 
-			// Last modified paths
+		messageResources.setServletContext(ctx);
 
-			if (_log.isDebugEnabled()) {
-				_log.debug("Last modified paths");
-			}
+		WebAppPool.put(
+			_companyIdString, Globals.MESSAGES_KEY, messageResources);
 
-			if (_lastModifiedPaths == null) {
-				_lastModifiedPaths = CollectionFactory.getHashSet();
+		// Last modified paths
 
-				for (int i = 0;; i++) {
-					String lastModifiedPath =
-						PropsUtil.get(PropsUtil.LAST_MODIFIED_PATH + i);
+		if (_log.isDebugEnabled()) {
+			_log.debug("Last modified paths");
+		}
 
-					if (lastModifiedPath == null) {
-						break;
-					}
-					else {
-						_lastModifiedPaths.add(lastModifiedPath);
-					}
+		if (_lastModifiedPaths == null) {
+			_lastModifiedPaths = CollectionFactory.getHashSet();
+
+			for (int i = 0;; i++) {
+				String lastModifiedPath =
+					PropsUtil.get(PropsUtil.LAST_MODIFIED_PATH + i);
+
+				if (lastModifiedPath == null) {
+					break;
 				}
+				else {
+					_lastModifiedPaths.add(lastModifiedPath);
+				}
 			}
+		}
 
-			// Process startup events
+		// Process startup events
 
-			if (_log.isDebugEnabled()) {
-				_log.debug("Process startup events");
-			}
+		if (_log.isDebugEnabled()) {
+			_log.debug("Process startup events");
+		}
 
-			try {
+		try {
+			if (defaultCompany) {
 				EventsProcessor.process(PropsUtil.getArray(
 					PropsUtil.GLOBAL_STARTUP_EVENTS), true);
-
-				EventsProcessor.process(PropsUtil.getArray(
-					PropsUtil.APPLICATION_STARTUP_EVENTS),
-					new String[] {_companyIdString});
 			}
-			catch (Exception e) {
-				_log.error(e, e);
-			}
 
-			// Portal instance
+			EventsProcessor.process(PropsUtil.getArray(
+				PropsUtil.APPLICATION_STARTUP_EVENTS),
+				new String[] {_companyIdString});
+		}
+		catch (Exception e) {
+			_log.error(e, e);
+		}
 
-			if (_log.isDebugEnabled()) {
-				_log.debug("Portal instance " + _companyId);
-			}
+		// Portal instance
 
-			PortalInstances.init(_companyId);
+		if (_log.isDebugEnabled()) {
+			_log.debug("Portal instance " + _companyId);
 		}
+
+		PortalInstances.init(_companyId);		
 	}
 
 	public void callParentService(
@@ -517,6 +543,9 @@
 			return;
 		}
 
+		// Override cached companyId
+		long _companyId = VirtualHostingUtil.getCompanyId(req);
+		
 		HttpSession ses = req.getSession();
 
 		// Test CAS auto login
@@ -608,6 +637,7 @@
 
 		// WebKeys.COMPANY_ID variable
 
+		/*
 		Long companyIdObj = (Long)ctx.getAttribute(WebKeys.COMPANY_ID);
 
 		if (portalCtx.getAttribute(WebKeys.COMPANY_ID) == null) {
@@ -617,7 +647,9 @@
 		if (ses.getAttribute(WebKeys.COMPANY_ID) == null) {
 			ses.setAttribute(WebKeys.COMPANY_ID, companyIdObj);
 		}
-
+		*/
+		Long companyIdObj = new Long(_companyId);
+		ses.setAttribute(WebKeys.COMPANY_ID, companyIdObj);
 		req.setAttribute(WebKeys.COMPANY_ID, companyIdObj);
 
 		CompanyThreadLocal.setCompanyId(companyIdObj.longValue());
@@ -948,11 +980,20 @@
 
 	public void destroy() {
 
+		
+
+		destroyCompany(_companyId, _companyIdString);
+
+		// Parent
+
+		super.destroy();
+	}
+	
+	public  void destroyCompany(long companyId, String companyWebId) {
 		// Destroy portlets
-
 		try {
 			Iterator itr = PortletLocalServiceUtil.getPortlets(
-				_companyId).iterator();
+				companyId).iterator();
 
 			while (itr.hasNext()) {
 				Portlet portlet = (Portlet)itr.next();
@@ -971,20 +1012,17 @@
 		}
 
 		try {
+			if (_companyId == companyId) {
+				EventsProcessor.process(PropsUtil.getArray(
+					PropsUtil.GLOBAL_SHUTDOWN_EVENTS), true);
+			}
 			EventsProcessor.process(PropsUtil.getArray(
-				PropsUtil.GLOBAL_SHUTDOWN_EVENTS), true);
-
-			EventsProcessor.process(PropsUtil.getArray(
 				PropsUtil.APPLICATION_SHUTDOWN_EVENTS),
-				new String[] {_companyIdString});
+				new String[] {companyWebId});
 		}
 		catch (Exception e) {
 			_log.error(e, e);
-		}
-
-		// Parent
-
-		super.destroy();
+		}		
 	}
 
 	private void _checkWebSettings(String xml) throws DocumentException {
Index: portal-ejb/src/com/liferay/portal/util/VirtualHostingUtil.java
===================================================================
--- portal-ejb/src/com/liferay/portal/util/VirtualHostingUtil.java	(revision 0)
+++ portal-ejb/src/com/liferay/portal/util/VirtualHostingUtil.java	(revision 0)
@@ -0,0 +1,311 @@
+package com.liferay.portal.util;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.Properties;
+
+import javax.servlet.ServletRequest;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.liferay.portal.model.Company;
+import com.liferay.portal.service.CompanyLocalServiceUtil;
+import com.liferay.portal.servlet.LuceneServlet;
+import com.liferay.portal.servlet.MainServlet;
+import com.liferay.util.GetterUtil;
+import com.liferay.util.StringUtil;
+
+public class VirtualHostingUtil implements Runnable {
+
+	private static final String BUNDLE_NAME = "asp-hosts.properties";
+
+	private static final String REFRESH = "refresh";
+
+	private static final String SHARED_VIRTUAL_HOSTING_ENABLED = "shared.virtual.hosting.enabled";
+
+	private static final String SHARED_VIRTUAL_HOSTING_CONFIG_FILE = "shared.virtual.hosting.config.file";
+
+	private static final String THREAD_NAME = "ASP VirtualHosting properties watcher";
+
+	private static final long MIN_REFRESH = 5000;
+
+	private static Thread _thread;
+
+	private static long _companyId;
+	
+	private static String _companyWebId;
+
+	private static String _cfgFilePath;
+
+	private static long _refresh = MIN_REFRESH;
+
+	private static long _lastUpdate = 0;
+
+	private static Log _log = LogFactory.getLog(VirtualHostingUtil.class);
+
+	private static Map _mappings = new HashMap();
+	
+	private static Map _companyIds = new HashMap();
+	
+	private static Map _companyWebIds = new HashMap();
+
+	private static boolean _enabled = false;
+
+	private static MainServlet _mainServlet;
+
+	private static LuceneServlet _luceneServlet;
+
+	public static void init(long companyId, String companyWebId, MainServlet mainServlet) {
+		_companyId = companyId;
+		_companyWebId = companyWebId;
+		_mainServlet = mainServlet;
+		if (GetterUtil
+				.getBoolean(PropsUtil.get(SHARED_VIRTUAL_HOSTING_ENABLED))) {
+			_enabled = true;
+			_cfgFilePath = PropsUtil.get(SHARED_VIRTUAL_HOSTING_CONFIG_FILE);
+			checkProperties();
+			String[] otherIds = getCompanyIds();
+			_log.debug("This host serves " + otherIds.length + "+1 companies");
+			_thread = new Thread(new VirtualHostingUtil(), THREAD_NAME);
+			_thread.setPriority(Thread.MIN_PRIORITY);
+			_thread.setDaemon(true);
+			_thread.start();
+		} else {
+			_log.debug("shared virtual hosting is dissabled");
+			;
+		}
+	}
+
+	public static void setLuceneServlet(LuceneServlet luceneServlet) {
+		_luceneServlet = luceneServlet;
+	}
+
+	public void run() {
+		for (;;) {
+			try {
+				Thread.sleep(_refresh);
+				checkProperties();
+			} catch (Exception e) {
+				_log.error(e.getMessage());
+			}
+		}
+	}
+
+	public static Properties loadProperties(String name) {
+		try {
+			URL url = new URL("file://" + _cfgFilePath);
+			_log.debug("URL: " + url);
+			Properties props = new Properties();
+			props.load(url.openStream());
+			_log.debug("Props: " + props.toString());
+			return props;
+		} catch (Exception e) {
+			_log.error(e.getMessage());
+			return null;
+		}
+	}
+
+	private static void checkProperties() {
+		try {
+			long curTime = System.currentTimeMillis();
+			Properties bundle;
+			if ((_lastUpdate + _refresh) < curTime) {
+				_log.debug("reloading properties");
+				bundle = loadProperties(BUNDLE_NAME);
+				if (bundle == null) {
+					_log.error("No properties loaded");
+					return;
+				}
+				Map mappingsTmp = new HashMap();
+				long refreshTmp = _refresh;
+				Iterator keys = bundle.keySet().iterator();
+				String curKey;
+				while (keys.hasNext()) {
+					curKey = (String) keys.next();
+					if (curKey.equals(REFRESH)) {
+						try {
+							refreshTmp = 1000 * Long.parseLong(bundle
+									.getProperty(curKey));
+							if (refreshTmp < MIN_REFRESH) {
+								refreshTmp = MIN_REFRESH;
+							}
+							_log.debug("New refresh time " + refreshTmp + "ms");
+						} catch (NumberFormatException e) {
+							_log.error(e.getMessage());
+						}
+					} else {
+						try {
+							Company company = CompanyLocalServiceUtil.checkCompany(curKey);
+							Long companyId = new Long(company.getCompanyId());
+							String companyWebId = company.getWebId();
+							// Cache company id to web id mapping
+							_companyIds.put(companyWebId, companyId);
+							// Cache web id to company id mapping
+							_companyWebIds.put(companyId, companyWebId);
+							String[] domains = StringUtil.split(bundle
+									.getProperty(curKey));
+							for (int i = 0; i < domains.length; i++) {
+								mappingsTmp.put(domains[i], companyId);
+								_log.debug("Added mapping for " + domains[i] + "->"
+										+ curKey + " with companyId " + companyId);
+							}
+						} catch (Exception e) {
+							_log.error(e, e);
+						}
+					}
+				}
+				startNewCompanys(mappingsTmp);
+				_refresh = refreshTmp;
+				_lastUpdate = curTime;
+				Map oldMappings = _mappings;
+				_mappings = mappingsTmp;
+				stopRemovedCompanys(oldMappings);
+			}
+		} catch (MissingResourceException e) {
+			_log.error(e.getMessage());
+		}
+	}
+
+	private static void startNewCompanys(Map newMappings) {
+		String[] newCompanys = getCompanyIds(newMappings, false);
+		String[] oldCompanys = getCompanyIds();
+		for (int i = 0; i < newCompanys.length; i++) {
+			boolean found = false;
+			for (int j = 0; j < oldCompanys.length && !found; j++) {
+				found = found || newCompanys[i].equals(oldCompanys[j]);
+			}
+			if (!found) {
+				_log.info("found new company_id=" + newCompanys[i]);
+				try {
+					// should not happen, but for safety
+					if (_mainServlet != null) {
+						_mainServlet.initCompany(newCompanys[i], false);
+					}
+
+					// Lucene servlet may not have been initialised
+					// if we get called from the startup process (MainServlet)
+					if (_luceneServlet != null) {
+						_luceneServlet.initCompany(((Long)_companyIds.get(newCompanys[i])).longValue());
+					}
+				} catch (Exception e) {
+					_log.error(e);
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	private static void stopRemovedCompanys(Map oldMappings) {
+		String[] newCompanys = getCompanyIds();
+		String[] oldCompanys = getCompanyIds(oldMappings, false);
+
+		for (int i = 0; i < oldCompanys.length; i++) {
+			boolean found = false;
+			for (int j = 0; j < newCompanys.length && !found; j++) {
+				found = found || oldCompanys[i].equals(newCompanys[j]);
+			}
+			if (!found) {
+				_log.info("removing old company_id=" + oldCompanys[i]);
+				try {
+					// should not happen, but for safety?
+					if (_mainServlet != null) {
+						_mainServlet.destroyCompany(((Long)_companyIds.get(oldCompanys[i])).longValue(), oldCompanys[i]);
+					}
+					if (_luceneServlet != null) {
+						_luceneServlet.destroyCompany(((Long)_companyIds.get(oldCompanys[i])).longValue());
+					}
+				} catch (Exception e) {
+					_log.error(e);
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	public static long getCompanyId(ServletRequest req) {
+		String _host = req.getServerName();
+		return getCompanyIdForHost(_host);
+	}
+
+	private static long getCompanyIdForHost(String host) {
+		// Return default company if not enabled
+		if (!_enabled) {
+			return _companyId;
+		}
+		// explicit value "host.domain.tld"
+		Long val = (Long) _mappings.get(host);
+		if (val != null) {
+			_log.debug("Request for ASP host: " + host + " returns company_id "
+					+ val + " (matched from *." + val + ")");
+			return val.longValue();
+		}
+
+		// "*.domain.tld" or similar
+		Iterator keys = _mappings.keySet().iterator();
+		while (keys.hasNext()) {
+			String curKey = (String) keys.next();
+			Long curValue = (Long) _mappings.get(curKey);
+			if (curKey.startsWith("*.")) {
+				curKey = curKey.substring(curKey.indexOf('.') + 1);
+				if (host.contains(curKey)) {
+					_log.debug("Request for ASP host: " + host
+							+ " returns company_id " + curValue
+							+ " (matched from *." + curKey + ")");
+					return curValue.longValue();
+				}
+			}
+		}
+
+		// "*" any domain gets managed by this id
+		val = (Long) _mappings.get("*");
+		if (val != null) {
+			_log.debug("Request for ASP host: " + host + " returns company_id "
+					+ val + " (matched from *)");
+			return val.longValue();
+		}
+
+		_log.debug("Request for ASP host: " + host + " returns company_id "
+				+ _companyId);
+		return _companyId;
+	}
+
+	public static String[] getAllCompanyIds() {
+		return getCompanyIds(true);
+	}
+
+	public static String[] getCompanyIds() {
+		return getCompanyIds(false);
+	}
+
+	public static String[] getCompanyIds(boolean includeMainId) {
+		return getCompanyIds(_mappings, includeMainId);
+	}
+
+	public static String[] getCompanyIds(Map mappings, boolean includeMainId) {
+		//Map ids = new HashMap();
+		List ids = new ArrayList();
+		Iterator keys = mappings.keySet().iterator();
+		while (keys.hasNext()) {
+			String curKey = (String) keys.next();
+			Long curValue = (Long) mappings.get(curKey);
+			if (curValue.longValue() != _companyId || includeMainId) {
+				ids.add(curValue);
+			}
+		}
+		String[] retVal = new String[ids.size()];
+		keys = ids.iterator();
+		int i = 0;
+		while (keys.hasNext()) {
+			Long curKey = (Long) keys.next();
+			retVal[i++] = (String)_companyWebIds.get(curKey);
+		}
+		return retVal;
+	}
+
+}
