/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.enterprise.web.reconfig;
import java.util.ArrayList;
import com.sun.enterprise.admin.event.AdminEventListenerException;
import com.sun.enterprise.admin.event.http.HSAccessLogEvent;
import com.sun.enterprise.admin.event.http.HSAccessLogEventListener;
import com.sun.enterprise.admin.event.http.HSVirtualServerEvent;
import com.sun.enterprise.admin.event.http.HSVirtualServerEventListener;
import com.sun.enterprise.admin.event.http.HSServiceEvent;
import com.sun.enterprise.admin.event.http.HSServiceEventListener;
import com.sun.enterprise.admin.event.http.HSHttpFileCacheEvent;
import com.sun.enterprise.admin.event.http.HSHttpFileCacheEventListener;
import com.sun.enterprise.admin.event.http.HSHttpListenerEvent;
import com.sun.enterprise.admin.event.http.HSHttpListenerEventListener;
import com.sun.enterprise.admin.event.http.HSHttpProtocolEvent;
import com.sun.enterprise.admin.event.http.HSHttpProtocolEventListener;
import com.sun.enterprise.admin.event.http.HSConnectionPoolEvent;
import com.sun.enterprise.admin.event.http.HSConnectionPoolEventListener;
import com.sun.enterprise.admin.event.http.HSKeepAliveEvent;
import com.sun.enterprise.admin.event.http.HSKeepAliveEventListener;
import com.sun.enterprise.admin.event.http.HSRequestProcessingEvent;
import com.sun.enterprise.admin.event.http.HSRequestProcessingEventListener;
import com.sun.enterprise.config.ConfigAdd;
import com.sun.enterprise.config.ConfigBean;
import com.sun.enterprise.config.ConfigChange;
import com.sun.enterprise.config.ConfigContext;
import com.sun.enterprise.config.ConfigException;
import com.sun.enterprise.config.serverbeans.Config;
import com.sun.enterprise.config.serverbeans.ElementProperty;
import com.sun.enterprise.config.serverbeans.HttpListener;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.ServerBeansFactory;
import com.sun.enterprise.config.serverbeans.VirtualServer;
import com.sun.enterprise.web.PEWebContainer;
/**
* Class responsible for handling dynamic reconfiguration events for
* various elements in domain.xml.
*
* @author Jean-Francois Arcand
* @author Jan Luehe
*/
public class ReconfigListener
implements HSAccessLogEventListener,
HSHttpListenerEventListener,
HSServiceEventListener,
HSVirtualServerEventListener,
HSHttpProtocolEventListener,
HSHttpFileCacheEventListener,
HSConnectionPoolEventListener,
HSKeepAliveEventListener,
HSRequestProcessingEventListener {
private PEWebContainer webContainer;
public ReconfigListener(PEWebContainer webContainer) {
this.webContainer = webContainer;
}
/*
* Dynamic reconfig events pertaining to <access-log>
*/
public void handleDelete(HSAccessLogEvent event)
throws AdminEventListenerException {
// Ignore
}
public void handleUpdate(HSAccessLogEvent event)
throws AdminEventListenerException {
if (webContainer == null || event == null) {
return;
}
try {
ConfigContext configContext = event.getConfigContext();
Config config = ServerBeansFactory.getConfigBean(configContext);
if (config == null) {
return;
}
webContainer.updateAccessLog(config.getHttpService());
} catch (Exception e) {
throw new AdminEventListenerException(e);
}
}
public void handleCreate(HSAccessLogEvent event)
throws AdminEventListenerException {
// Ignore
}
/*
* Dynamic reconfig events pertaining to <http-listener>
*/
/**
* Create a new http-listener.
*/
public void handleCreate(HSHttpListenerEvent event)
throws AdminEventListenerException {
if (webContainer == null || event == null) {
return;
}
try {
ConfigContext configContext = event.getConfigContext();
Config config = ServerBeansFactory.getConfigBean(configContext);
if ( config == null) return;
ConfigAdd configAdd = null;
ArrayList configChangeList = event.getConfigChangeList();
HttpListener httpBean = null;
String xpath = null;
Object object;
Object configObject;
for (int i=0; i < configChangeList.size(); i++){
configObject = configChangeList.get(i);
if ( configObject instanceof ConfigAdd) {
configAdd = (ConfigAdd)configObject;
xpath = configAdd.getXPath();
if( xpath != null){
object = configContext.exactLookup(xpath);
if ( object instanceof HttpListener){
httpBean = (HttpListener)object;
webContainer.createConnector(httpBean,
config.getHttpService());
}
}
}
}
} catch (Exception ex) {
throw new AdminEventListenerException(ex);
}
}
/**
* Update an existing http-listener.
*/
public void handleUpdate(HSHttpListenerEvent event)
throws AdminEventListenerException {
if (webContainer == null || event == null) {
return;
}
try {
ConfigContext configContext = event.getConfigContext();
Config config = ServerBeansFactory.getConfigBean(configContext);
if ( config == null) return;
ConfigChange configChange = null;
ArrayList<ConfigChange> configChangeList =
event.getConfigChangeList();
HttpListener httpBean = null;
String xpath = null;
String parentXpath = null;
Object object;
ElementProperty elementProperty = null;
for (int i=0; i < configChangeList.size(); i++){
configChange = configChangeList.get(i);
xpath = configChange.getXPath();
if (xpath != null) {
object = configContext.exactLookup(xpath);
if (object != null) {
if (object instanceof HttpListener) {
if ( ((HttpListener)object).getDefaultVirtualServer()
.equals(com.sun.enterprise.web.VirtualServer.ADMIN_VS)){
if (configChangeList.size() == 1){
throw new AdminEventListenerException("Restart required");
} else {
continue;
}
}
webContainer.updateConnector(
(HttpListener)object,
config.getHttpService(),
configContext);
} else if (object instanceof ElementProperty) {
// Property has been added or updated
parentXpath = configChange.getParentXPath();
if (parentXpath == null) {
parentXpath =
xpath.substring(0, xpath.lastIndexOf("/"));
}
httpBean = (HttpListener)
configContext.exactLookup(parentXpath);
webContainer.updateConnector(
httpBean,
config.getHttpService(),
configContext);
}
} else {
// Property has been deleted
parentXpath =
xpath.substring(0, xpath.lastIndexOf("/"));
httpBean = (HttpListener)
configContext.exactLookup(parentXpath);
webContainer.updateConnector(
httpBean,
config.getHttpService(),
configContext);
}
}
}
} catch (Exception ex) {
throw new AdminEventListenerException(ex);
}
}
/**
* Delete an existing http-listener.
*
* Implementation note: we cannot use the same approach used when
* handling create/update event since the element is deleted before this
* method is invoked (strange behaviour). Instead we need to find by
* ourself which http-listener has been deleted.
*/
public void handleDelete(HSHttpListenerEvent event)
throws AdminEventListenerException {
if (webContainer == null || event == null) {
return;
}
try {
ConfigContext configContext = event.getConfigContext();
Config config = ServerBeansFactory.getConfigBean(configContext);
if ( config == null) return;
webContainer.deleteConnector(config.getHttpService());
} catch( Exception ex){
throw new AdminEventListenerException(ex);
}
}
/*
* Dynamic reconfig events pertaining to <http-service>
*/
public void handleDelete(HSServiceEvent event)
throws AdminEventListenerException {
// Ignore
}
public void handleUpdate(HSServiceEvent event)
throws AdminEventListenerException {
if (webContainer == null || event == null) {
return;
}
try {
ConfigContext configContext = event.getConfigContext();
Config config = ServerBeansFactory.getConfigBean(configContext);
if (config == null) {
return;
}
webContainer.updateHttpService(config.getHttpService(),
configContext);
} catch (Exception e) {
throw new AdminEventListenerException(e);
}
}
public void handleCreate(HSServiceEvent event)
throws AdminEventListenerException {
// Ignore
}
/*
* Dynamic reconfig events pertaining to <virtual-server>
*/
/**
* Create a new virtual-server.
*/
public void handleCreate(HSVirtualServerEvent event)
throws AdminEventListenerException {
if (webContainer == null || event == null) {
return;
}
try {
ConfigContext configContext = event.getConfigContext();
Config config = ServerBeansFactory.getConfigBean(configContext);
if ( config == null) return;
ConfigAdd configAdd = null;
ArrayList configChangeList = event.getConfigChangeList();
VirtualServer vsBean = null;
String xpath = null;
Server serverBean = ServerBeansFactory.getServerBean(configContext);
ElementProperty elementProperty = null;
Object object;
Object configObject;
for (int i=0; i < configChangeList.size(); i++){
configObject = configChangeList.get(i);
if ( configObject instanceof ConfigAdd) {
configAdd = (ConfigAdd)configObject;
xpath = configAdd.getXPath();
if( xpath != null){
object = configContext.exactLookup(xpath);
if ( object instanceof VirtualServer){
vsBean = (VirtualServer)object;
webContainer.createHost(vsBean,configContext,true);
} else if (object instanceof ElementProperty) {
xpath = xpath.substring(0,xpath.lastIndexOf("/"));
vsBean = (VirtualServer)configContext.exactLookup(xpath);
elementProperty = (ElementProperty)object;
webContainer.updateHostProperties(
vsBean,
elementProperty.getName(),
elementProperty.getValue(),
config.getHttpService(),
config.getSecurityService());
}
}
}
}
} catch (Exception ex) {
throw new AdminEventListenerException(ex);
}
}
/**
* Update an existing virtual-server.
*/
public void handleUpdate(HSVirtualServerEvent event)
throws AdminEventListenerException {
if (webContainer == null || event == null) {
return;
}
try {
ConfigContext configContext = event.getConfigContext();
Config config = ServerBeansFactory.getConfigBean(configContext);
if ( config == null) return;
ConfigChange configChange = null;
ArrayList<ConfigChange> configChangeList =
event.getConfigChangeList();
VirtualServer vsBean = null;
String xpath = null;
String parentXpath = null;
Server serverBean = ServerBeansFactory.getServerBean(configContext);
ElementProperty elementProperty = null;
Object object;
for (int i=0; i < configChangeList.size(); i++){
configChange = configChangeList.get(i);
xpath = configChange.getXPath();
if (xpath != null) {
object = configContext.exactLookup(xpath);
if (object != null) {
if ( object instanceof VirtualServer){
webContainer.updateHost((VirtualServer)object,
config.getHttpService(),
serverBean);
} else if (object instanceof ElementProperty) {
// Property has been added or updated
parentXpath = configChange.getParentXPath();
if (parentXpath == null) {
parentXpath =
xpath.substring(0, xpath.lastIndexOf("/"));
}
vsBean = (VirtualServer)
configContext.exactLookup(parentXpath);
elementProperty = (ElementProperty)object;
webContainer.updateHostProperties(
vsBean,
elementProperty.getName(),
elementProperty.getValue(),
config.getHttpService(),
config.getSecurityService());
}
} else {
// Property has been deleted.
// Determine the property's name
int lastSlash = xpath.lastIndexOf("/");
parentXpath = xpath.substring(0, lastSlash);
String propName = xpath.substring(lastSlash);
if (propName != null) {
// e.g., /element-property[@name='sso-enabled']
int beginQuote = propName.indexOf("'");
int endQuote = propName.lastIndexOf("'");
if (endQuote > beginQuote) {
propName = propName.substring(beginQuote+1,
endQuote);
vsBean = (VirtualServer)
configContext.exactLookup(parentXpath);
webContainer.updateHostProperties(
vsBean,
propName,
null,
config.getHttpService(),
config.getSecurityService());
}
}
}
}
}
} catch (Exception ex) {
throw new AdminEventListenerException(ex);
}
}
/**
* Delete an existing virtual-server.
*
* Implementation note: we cannot use the same approach used when
* handling create/update event since the element is deleted before this
* method is invoked (strange behaviour). Instead we need to find by
* ourself which virtual-server has been deleted.
*/
public void handleDelete(HSVirtualServerEvent event)
throws AdminEventListenerException {
if (webContainer == null || event == null) {
return;
}
try {
ConfigContext configContext = event.getConfigContext();
Config config = ServerBeansFactory.getConfigBean(configContext);
if (config != null) {
webContainer.deleteHost(config.getHttpService());
}
} catch( Exception ex){
throw new AdminEventListenerException(ex);
}
}
/*
* Dynamic reconfig events pertaining to <http-protocol>
*/
public void handleDelete(HSHttpProtocolEvent event)
throws AdminEventListenerException {
// Ignore
}
public void handleUpdate(HSHttpProtocolEvent event)
throws AdminEventListenerException {
if (webContainer == null) {
return;
}
try {
ConfigContext configContext = event.getConfigContext();
Config config = ServerBeansFactory.getConfigBean(configContext);
if (config == null) {
return;
}
webContainer.updateHttpService(config.getHttpService(),
configContext);
} catch (Exception e) {
throw new AdminEventListenerException(e);
}
}
public void handleCreate(HSHttpProtocolEvent event)
throws AdminEventListenerException {
// Ignore
}
/*
* Dynamic reconfig events pertaining to <http-file-cache>
*/
public void handleDelete(HSHttpFileCacheEvent event)
throws AdminEventListenerException {
// Ignore
}
public void handleUpdate(HSHttpFileCacheEvent event)
throws AdminEventListenerException {
if (webContainer == null) {
return;
}
try {
ConfigContext configContext = event.getConfigContext();
Config config = ServerBeansFactory.getConfigBean(configContext);
if (config == null) {
return;
}
webContainer.updateHttpService(config.getHttpService(),
configContext);
} catch (Exception e) {
throw new AdminEventListenerException(e);
}
}
public void handleCreate(HSHttpFileCacheEvent event)
throws AdminEventListenerException {
// Ignore
}
/*
* Dynamic reconfig events pertaining to <connection-pool>
*/
public void handleDelete(HSConnectionPoolEvent event)
throws AdminEventListenerException {
// Ignore
}
public void handleUpdate(HSConnectionPoolEvent event)
throws AdminEventListenerException {
if (webContainer == null) {
return;
}
try {
ConfigContext configContext = event.getConfigContext();
Config config = ServerBeansFactory.getConfigBean(configContext);
if (config == null) {
return;
}
webContainer.updateHttpService(config.getHttpService(),
configContext);
} catch (Exception e) {
throw new AdminEventListenerException(e);
}
}
public void handleCreate(HSConnectionPoolEvent event)
throws AdminEventListenerException {
// Ignore
}
/*
* Dynamic reconfig events pertaining to <keep-alive>
*/
public void handleDelete(HSKeepAliveEvent event)
throws AdminEventListenerException {
// Ignore
}
public void handleUpdate(HSKeepAliveEvent event)
throws AdminEventListenerException {
if (webContainer == null) {
return;
}
try {
ConfigContext configContext = event.getConfigContext();
Config config = ServerBeansFactory.getConfigBean(configContext);
if (config == null) {
return;
}
webContainer.updateHttpService(config.getHttpService(),
configContext);
} catch (Exception e) {
throw new AdminEventListenerException(e);
}
}
public void handleCreate(HSKeepAliveEvent event)
throws AdminEventListenerException {
// Ignore
}
/*
* Dynamic reconfig events pertaining to <request-processing>
*/
public void handleDelete(HSRequestProcessingEvent event)
throws AdminEventListenerException {
// Ignore
}
public void handleUpdate(HSRequestProcessingEvent event)
throws AdminEventListenerException {
if (webContainer == null) {
return;
}
try {
ConfigContext configContext = event.getConfigContext();
Config config = ServerBeansFactory.getConfigBean(configContext);
if (config == null) {
return;
}
webContainer.updateHttpService(config.getHttpService(),
configContext);
} catch (Exception e) {
throw new AdminEventListenerException(e);
}
}
public void handleCreate(HSRequestProcessingEvent event)
throws AdminEventListenerException {
// Ignore
}
}