/* * Copyright (c) 2008, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.wso2.carbon.proxyadmin.observer; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.impl.builder.StAXOMBuilder; import org.apache.axis2.AxisFault; import org.apache.axis2.description.*; import org.apache.axis2.engine.AxisConfiguration; import org.apache.axis2.engine.AxisEvent; import org.apache.axis2.engine.AxisObserver; import org.apache.axis2.util.JavaUtils; import org.apache.axis2.util.PolicyUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.neethi.Policy; import org.apache.neethi.PolicyEngine; import org.apache.rampart.Rampart; import org.apache.synapse.SynapseConstants; import org.apache.synapse.config.SynapseConfigUtils; import org.apache.synapse.config.SynapseConfiguration; import org.apache.synapse.core.axis2.ProxyService; import org.apache.synapse.util.PolicyInfo; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.core.RegistryResources; import org.wso2.carbon.mediation.initializer.ServiceBusConstants; import org.wso2.carbon.mediation.initializer.persistence.MediationPersistenceManager; import org.wso2.carbon.mediation.initializer.services.SynapseEnvironmentService; import org.wso2.carbon.proxyadmin.ProxyAdminException; import org.wso2.carbon.registry.core.Collection; import org.wso2.carbon.registry.core.Registry; import org.wso2.carbon.registry.core.RegistryConstants; import org.wso2.carbon.registry.core.Resource; import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.registry.core.session.UserRegistry; import org.wso2.carbon.security.SecurityConstants; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; /** * Proxy observer observe the Proxy service in runtime and update the synapse Configuration */ public class ProxyObserver implements AxisObserver { private SynapseEnvironmentService synapseEnvironmentService; private Registry configSystemRegistry; private static final Log log = LogFactory.getLog(ProxyObserver.class); private static final String[] DEFAULT_MODULES = new String[] { "addressing", "ServerAdminModule", "wso2statistics", "POXSecurityModule", "pagination" ,"wso2tracer" }; /** * Constructs a new ProxyObserver using the given SynapseEnvironmentService. This * constructor ensures that all the created proxy observer instances have a * non-null SynapseConfiguration. Attempting to create a proxy observer with * a null SynapseConfiguration would result in an exception. * TODO: because of a bug in current equinox framework version, we no longer get events when new * TODO: synapse environment created. So changed proxy observer config to take reference of * TODO: synapseEnvService and obtaing synapse config from it See : ESBJAVA-1029 * @param synapseEnvironmentService the Synapse * @param configRegistry the registry * @throws ProxyAdminException if the SynapseConfiguration is null */ public ProxyObserver(SynapseEnvironmentService synapseEnvironmentService, Registry configRegistry) throws ProxyAdminException { if (synapseEnvironmentService.getSynapseEnvironment().getSynapseConfiguration() == null) { String msg = "Unable to initialize a ProxyObserver with a null SynapseConfiguration"; log.error(msg); throw new ProxyAdminException(msg); } this.synapseEnvironmentService = synapseEnvironmentService; this.configSystemRegistry = configRegistry; } public void init(AxisConfiguration axisConfiguration) { } public void serviceUpdate(AxisEvent event, AxisService axisService) { Parameter serviceTypeParam = axisService.getParameter( SynapseConstants.SERVICE_TYPE_PARAM_NAME); if (serviceTypeParam == null || !SynapseConstants.PROXY_SERVICE_TYPE.equals( serviceTypeParam.getValue().toString())) { // We are only interested about the proxy services return; } if (getSynapseConfiguration() == null) { // Somehow the underlying SynapseConfiguration has become null after // creating the proxy observer. May be the user is manipulating bundles // through the OSGi console or the system is shutting down. if (log.isDebugEnabled()) { log.debug("SynapseConfiguration in ProxyObserver is null. The service" + " update event will not be processed further."); } return; } if (CarbonConstants.POLICY_ADDED == event.getEventType()) { updateProxyServicePolicies(axisService, getSynapseConfiguration()); } if (CarbonConstants.AxisEvent.TRANSPORT_BINDING_ADDED == event.getEventType()) { ProxyService proxy = getSynapseConfiguration().getProxyService(axisService.getName()); if (proxy != null && proxy.getTransports() != null) { List<String> transports = axisService.getExposedTransports(); for (String trp : transports) { if (!proxy.getTransports().contains(trp)) { proxy.getTransports().add(trp); } } } } if (AxisEvent.SERVICE_REMOVE == event.getEventType()) { Parameter keepServiceHistoryParam = axisService.getParameter( CarbonConstants.KEEP_SERVICE_HISTORY_PARAM); Parameter originator = axisService.getParameter("originator"); boolean keepHistory = keepServiceHistoryParam != null && JavaUtils.isTrue(keepServiceHistoryParam.getValue()); //Only remove proxy config from storage if service remove request coming from // Service listing UI. This check will prevent proxy xml deleting from file system //during hot update if (originator != null && "ServiceAdmin".equals(originator.getValue().toString())) { if (!keepHistory) { ProxyService proxySvc = getSynapseConfiguration().getProxyService(axisService.getName()); if (proxySvc != null) { getSynapseConfiguration().removeProxyService(axisService.getName()); MediationPersistenceManager pm = getMediationPersistenceManager(); pm.deleteItem(proxySvc.getName(), proxySvc.getFileName(), ServiceBusConstants.ITEM_TYPE_PROXY_SERVICE); log.info("Deleted the proxy service : " + proxySvc.getName()); } else if (log.isDebugEnabled()) { log.debug("Proxy Service representing the service " + axisService.getName() + " of type proxy is not found in the SynapseConfiguration"); } } } } } public void moduleUpdate(AxisEvent event, AxisModule axisModule) { if (event != null && (event.getAxisDescription() instanceof AxisService || event.getAxisDescription() instanceof AxisOperation)) { AxisService axisService; if (event.getAxisDescription() instanceof AxisService) { axisService = (AxisService) event.getAxisDescription(); } else { axisService = ((AxisOperation) event.getAxisDescription()).getAxisService(); } Parameter serviceTypeParam = axisService.getParameter( SynapseConstants.SERVICE_TYPE_PARAM_NAME); if (serviceTypeParam == null || !SynapseConstants.PROXY_SERVICE_TYPE.equals( serviceTypeParam.getValue().toString())) { // We are only interested about the proxy services return; } if (getSynapseConfiguration() == null) { if (log.isDebugEnabled()) { log.debug("SynapseConfiguration in ProxyObserver is null. The module" + " update event will not be processed further."); } return; } if (CarbonConstants.POLICY_ADDED == event.getEventType()) { updateProxyServicePolicies(axisService, getSynapseConfiguration()); } if (AxisEvent.MODULE_ENGAGED == event.getEventType() && !isDefaultModule(axisModule)) { onEngageModule(axisService, axisModule, getSynapseConfiguration()); updateProxyServicePolicies(axisService, getSynapseConfiguration()); } if (AxisEvent.MODULE_DISENGAGED == event.getEventType() && !isDefaultModule(axisModule)) { onDisEngageModule(axisService, axisModule, getSynapseConfiguration()); updateProxyServicePolicies(axisService, getSynapseConfiguration()); } } } private boolean isDefaultModule(AxisModule module) { String name = module.getName(); for (String defaultModule : DEFAULT_MODULES) { if (defaultModule.equals(name)) { return true; } } return false; } public void serviceGroupUpdate(AxisEvent event, AxisServiceGroup axisServiceGroup) {} public void addParameter(Parameter parameter) throws AxisFault {} public void removeParameter(Parameter parameter) throws AxisFault {} public void deserializeParameters(OMElement omElement) throws AxisFault {} public Parameter getParameter(String s) { return null; } public ArrayList<Parameter> getParameters() { return null; } public boolean isParameterLocked(String s) { return false; } private void onEngageModule(AxisService service, AxisModule module, SynapseConfiguration config) { if (config.getProxyService(service.getName()) != null) { ProxyService proxy = config.getProxyService(service.getName()); if (module.getModule() instanceof Rampart) { proxy.setWsSecEnabled(true); } } } private void onDisEngageModule(AxisService service, AxisModule module, SynapseConfiguration config) { if (config.getProxyService(service.getName()) != null) { ProxyService proxy = config.getProxyService(service.getName()); if (module.getModule() instanceof Rampart) { proxy.setWsSecEnabled(false); proxy.getParameterMap().remove(SecurityConstants.SECURITY_POLICY_PATH); proxy.getParameterMap().remove("disableREST"); } } } private void updateProxyServicePolicies(AxisService axisService, SynapseConfiguration config) { if (config.getProxyService(axisService.getName()) == null) { if (log.isDebugEnabled()) { log.debug("Couldn't retrieve the proxy service with name " + axisService.getName() + " to update policies"); } return; } ProxyService proxyService = config.getProxyService(axisService.getName()); try { Registry registry = this.configSystemRegistry; String servicePath = RegistryResources.ROOT + "axis2" + RegistryConstants.PATH_SEPARATOR + "service-groups" + RegistryConstants.PATH_SEPARATOR + axisService.getAxisServiceGroup().getServiceGroupName() + RegistryConstants.PATH_SEPARATOR + "services" + RegistryConstants.PATH_SEPARATOR + axisService.getName(); String servicePoliciesPath = servicePath + RegistryConstants.PATH_SEPARATOR + "policies"; List<PolicyInfo> remainingPolicies = new ArrayList<PolicyInfo>(); for (PolicyInfo info : proxyService.getPolicies()) { if (!info.getPolicyKey().startsWith("conf:" + servicePoliciesPath)) { remainingPolicies.add(info); } } proxyService.setPolicies(remainingPolicies); if (registry.resourceExists(servicePoliciesPath)) { // there are service level policies Resource servicePoliciesResource = registry.get(servicePoliciesPath); if (servicePoliciesResource instanceof Collection) { Collection servicePoliciesCollection = (Collection) servicePoliciesResource; for (String servicePolicyResourcePath : servicePoliciesCollection.getChildren()) { PolicyInfo pi = handlePolicy(config, proxyService, servicePolicyResourcePath, (UserRegistry) registry); if (pi != null) { pi.setPolicyKey("conf:" + pi.getPolicyKey()); proxyService.addPolicyInfo(pi); } } } } // Update exposed transports if (axisService.getExposedTransports() != null && !axisService.getExposedTransports().isEmpty()) { proxyService.setTransports( new ArrayList<String>(axisService.getExposedTransports())); } else { proxyService.setTransports(new ArrayList()); } persistChanges(axisService.getName(), axisService.getAxisConfiguration()); } catch (RegistryException e) { log.error("Error checking the policies from the registry", e); } } private PolicyInfo handlePolicy(SynapseConfiguration config, ProxyService proxy, String policyPath, UserRegistry registry) throws RegistryException { if (!registry.resourceExists(policyPath)) { return null; } Resource policyResource = registry.get(policyPath); byte[] content = (byte[]) policyResource.getContent(); if (content == null || content.length == 0) { return null; } policyResource.discard(); ByteArrayInputStream in = new ByteArrayInputStream(content); Policy policy = getPolicy(in); if (policy != null && !policy.isEmpty()) { for (PolicyInfo pi : proxy.getPolicies()) { if (pi.isServicePolicy()) { config.getEntryDefinition(pi.getPolicyKey()); Policy proxyPolicy = PolicyEngine.getPolicy(SynapseConfigUtils.getStreamSource( config.getEntry(pi.getPolicyKey())).getInputStream()); if (proxyPolicy.equal(policy.normalize(false))) { return null; } } } return new PolicyInfo(policyPath); } return null; } private Policy getPolicy(InputStream is) { BufferedInputStream inputStream = new BufferedInputStream(is); try { XMLStreamReader parser = XMLInputFactory.newInstance(). createXMLStreamReader(inputStream); StAXOMBuilder builder = new StAXOMBuilder(parser); OMElement elem = builder.getDocumentElement(); return PolicyUtil.getPolicyFromOMElement(elem); } catch (XMLStreamException e) { return null; } finally { try { inputStream.close(); } catch (IOException ignored) {} } } private void persistChanges(String proxyName, AxisConfiguration axisConfiguration) { Parameter param = axisConfiguration.getParameter(ServiceBusConstants.SUSPEND_PERSISTENCE); if (param != null && Boolean.parseBoolean((String) param.getValue())) { return; } MediationPersistenceManager mpm = getMediationPersistenceManager(); if (mpm != null) { mpm.saveItem(proxyName, ServiceBusConstants.ITEM_TYPE_PROXY_SERVICE); } } private MediationPersistenceManager getMediationPersistenceManager() { Parameter p = getSynapseConfiguration().getAxisConfiguration().getParameter( ServiceBusConstants.PERSISTENCE_MANAGER); if (p != null) { return (MediationPersistenceManager) p.getValue(); } return null; } public void setSynapseEnvironmentService(SynapseEnvironmentService synapseEnvironmentService) { this.synapseEnvironmentService = synapseEnvironmentService; } private SynapseConfiguration getSynapseConfiguration() { return this.synapseEnvironmentService.getSynapseEnvironment().getSynapseConfiguration(); } }