/*
* Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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.mediation.library.service;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.locks.Lock;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axis2.AxisFault;
import org.apache.axis2.deployment.DeploymentException;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.SynapseException;
import org.apache.synapse.config.Entry;
import org.apache.synapse.config.SynapseConfiguration;
import org.apache.synapse.config.SynapsePropertiesLoader;
import org.apache.synapse.config.xml.EntryFactory;
import org.apache.synapse.config.xml.SynapseImportFactory;
import org.apache.synapse.config.xml.SynapseImportSerializer;
import org.apache.synapse.config.xml.SynapseXMLConfigurationFactory;
import org.apache.synapse.config.xml.XMLConfigConstants;
import org.apache.synapse.deployers.SynapseArtifactDeploymentStore;
import org.apache.synapse.libraries.imports.SynapseImport;
import org.apache.synapse.libraries.model.Library;
import org.apache.synapse.libraries.util.LibDeployerUtils;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.mediation.initializer.AbstractServiceBusAdmin;
import org.wso2.carbon.mediation.initializer.ServiceBusConstants;
import org.wso2.carbon.mediation.initializer.ServiceBusUtils;
import org.wso2.carbon.mediation.initializer.persistence.MediationPersistenceManager;
import org.wso2.carbon.mediation.library.util.LocalEntryUtil;
@SuppressWarnings({ "UnusedDeclaration" })
public class MediationLibraryAdminService extends AbstractServiceBusAdmin {
private static Log log = LogFactory.getLog(MediationLibraryAdminService.class);
public static final int MSGS_PER_PAGE = 10;
/**
* Get an XML configuration element for a message processor from the FE and
* creates and add the MessageStore to the synapse configuration.
*
* @param xml
* string that contain the message processor configuration.
* @throws AxisFault
* if some thing goes wrong when creating a MessageProcessor
* with the given xml.
*/
private void addImport(String xml) throws AxisFault {
try {
OMElement imprtElem = createElement(xml);
SynapseImport synapseImport = SynapseImportFactory.createImport(imprtElem, null);
if (synapseImport != null && synapseImport.getName() != null) {
SynapseConfiguration synapseConfiguration = getSynapseConfiguration();
String fileName = ServiceBusUtils.generateFileName(synapseImport.getName());
synapseImport.setFileName(fileName);
synapseConfiguration.addSynapseImport(synapseImport.getName(), synapseImport);
String synImportQualfiedName = LibDeployerUtils.getQualifiedName(synapseImport);
Library synLib =
getSynapseConfiguration().getSynapseLibraries()
.get(synImportQualfiedName);
if (synLib != null) {
LibDeployerUtils.loadLibArtifacts(synapseImport, synLib);
}
MediationPersistenceManager mp = getMediationPersistenceManager();
mp.saveItem(synapseImport.getName(), ServiceBusConstants.ITEM_TYPE_IMPORT);
} else {
String message = "Unable to create a Synapse Import for : " + xml;
handleException(log, message, null);
}
} catch (XMLStreamException e) {
String message = "Unable to create a Synapse Import for : " + xml;
handleException(log, message, e);
}
}
public void addImport(String libName, String packageName) throws AxisFault {
SynapseImport synImport = new SynapseImport();
synImport.setLibName(libName);
synImport.setLibPackage(packageName);
OMElement impEl = SynapseImportSerializer.serializeImport(synImport);
if (impEl != null) {
try {
addImport(impEl.toString());
} catch (AxisFault axisFault) {
handleException(log, "Could not add Synapse Import", axisFault);
}
} else {
handleException(log,
"Could not add Synapse Import. Invalid import params for libName : " +
libName + " packageName : " + packageName, null);
}
}
/**
* Method loads the Library artifact information
*
* @param libName
* @param packageName
* @return
* @throws AxisFault
*/
public LibraryInfo getLibraryInfo(String libName, String packageName) throws AxisFault {
SynapseImport synImport = new SynapseImport();
synImport.setLibName(libName);
synImport.setLibPackage(packageName);
SynapseConfiguration configuration = getSynapseConfiguration();
OMElement impEl = SynapseImportSerializer.serializeImport(synImport);
if (impEl != null) {
try {
SynapseImport synapseImport = configuration.getSynapseImports().get("{"+packageName+"}"+libName);
OMElement imprtElem = createElement(impEl.toString());
if(synapseImport == null) {
synapseImport = SynapseImportFactory.createImport(imprtElem, null);
}
if (synapseImport != null && synapseImport.getName() != null) {
// SynapseConfiguration synapseConfiguration =
// getSynapseConfiguration();
String fileName = ServiceBusUtils.generateFileName(synapseImport.getName());
synapseImport.setFileName(fileName);
String synImportQualfiedName = LibDeployerUtils.getQualifiedName(synapseImport);
Library synLib =
getSynapseConfiguration().getSynapseLibraries()
.get(synImportQualfiedName);
if (synLib != null) {
LibraryInfo info = new LibraryInfo();
info.setLibName(libName);
info.setPackageName(packageName);
List<LibraryArtifiactInfo> artifactsList =
new ArrayList<LibraryArtifiactInfo>();
for (Map.Entry<String, String> entry : synLib.getLibArtifactDetails()
.entrySet()) {
if (entry.getValue() != null && entry.getKey() != null) {
LibraryArtifiactInfo artifactInfo = new LibraryArtifiactInfo();
artifactInfo.setName(entry.getKey());
artifactInfo.setDescription(synLib.getArtifactDescription(entry.getKey()));
artifactsList.add(artifactInfo);
}
}
LibraryArtifiactInfo[] artifacts =
new LibraryArtifiactInfo[artifactsList.size()];
for (int i = 0; i < artifacts.length; i++) {
artifacts[i] = artifactsList.get(i);
}
info.setArtifacts(artifacts);
return info;
}
}
} catch (XMLStreamException e) {
String message = "Unable to create a Synapse Import for : ";
handleException(log, message, e);
}
}
return null;
}
/**
* Get the Synapse configuration for a Message processor
*
* @param qualifiedName
* name of the message processor
* @return XML String that contain the configuration
* @throws AxisFault
*/
public String getImport(String qualifiedName) throws AxisFault {
SynapseConfiguration configuration = getSynapseConfiguration();
assert configuration != null;
SynapseImport synapseImport = configuration.getSynapseImports().get(qualifiedName);
String xml = null;
if (synapseImport != null) {
xml = SynapseImportSerializer.serializeImport(synapseImport).toString();
} else {
handleException(log, "Library Import " + synapseImport + " does not exist", null);
}
return xml;
}
/**
* Delete the SynapseImport instance with given importQualifiedName in the
* synapse configuration
*
* @param importQualifiedName
* of the MessageProcessor to be deleted
* @throws AxisFault
* if Message processor does not exist
*/
public void deleteImport(String importQualifiedName) throws AxisFault {
SynapseConfiguration configuration = getSynapseConfiguration();
assert configuration != null;
if (configuration.getSynapseImports().containsKey(importQualifiedName)) {
SynapseImport synapseImport = configuration.removeSynapseImport(importQualifiedName);
String fileName = synapseImport.getFileName();
// get corresponding library for un-loading this import
Library synLib =
getSynapseConfiguration().getSynapseLibraries()
.get(importQualifiedName);
if (synLib != null) {
// this is a important step -> we need to unload what ever the
// components loaded thru this import
synLib.unLoadLibrary();
undeployingLocalEntries(synLib, configuration);
}
MediationPersistenceManager pm = getMediationPersistenceManager();
pm.deleteItem(synapseImport.getName(), fileName, ServiceBusConstants.ITEM_TYPE_IMPORT);
}
}
public void deleteLibrary(String libQualifiedName) throws Exception {
// If libQualifiedName is null throw an exception
if (libQualifiedName == null) {
handleException(log, "Library name can't be null", null);
return;
}
// CarbonApplication instance to delete
Library currentMediationLib = null;
SynapseConfiguration synConfigForTenant = getSynapseConfiguration();
if (synConfigForTenant != null) {
Collection<Library> appList = synConfigForTenant.getSynapseLibraries().values();
for (Library mediationLib : appList) {
if (libQualifiedName.equals(mediationLib.getQName().toString())) {
currentMediationLib = mediationLib;
}
}
// If requested application not found, throw an exception
if (currentMediationLib == null) {
handleException(log,
"No Mediation Library found of the name : " + libQualifiedName,
null);
return;
}
// deleting relevent configuration
deleteImport(libQualifiedName);
// Remove the app artifact file from repository, cApp hot undeployer
// will do the rest
String libFilePath = currentMediationLib.getFileName();
File file = new File(libFilePath);
if (file.exists() && !file.delete()) {
log.error("Artifact file couldn't be deleted for Mediation Library : " +
currentMediationLib.getQName().toString());
}
}
}
/**
* Get all the Current Message processor names defined in the configuration
*
* @return array of Strings that contains MessageStore names
* @throws AxisFault
*/
public String[] getAllImports() throws AxisFault {
SynapseConfiguration configuration = getSynapseConfiguration();
assert configuration != null;
Collection<String> names = configuration.getSynapseImports().keySet();
return names.toArray(new String[names.size()]);
}
/**
* Get all the Current Message processor names defined in the configuration
*
* @return array of Strings that contains MessageStore names
* @throws AxisFault
*/
public String[] getAllLibraries() throws AxisFault {
SynapseConfiguration configuration = getSynapseConfiguration();
assert configuration != null;
Collection<String> names = configuration.getSynapseLibraries().keySet();
return names.toArray(new String[names.size()]);
}
/**
* Get all the Current Message processor names defined in the configuration
*
* @return array of Strings that contains MessageStore names
* @throws AxisFault
*/
public LibraryInfo[] getAllLibraryInfo() throws AxisFault {
SynapseConfiguration configuration = getSynapseConfiguration();
assert configuration != null;
ArrayList<LibraryInfo> librarySet = new ArrayList<LibraryInfo>();
Collection<Library> libraries = configuration.getSynapseLibraries().values();
for (Library library : libraries) {
LibraryInfo libInfo = new LibraryInfo();
libInfo.setLibName(library.getQName().getLocalPart());
libInfo.setPackageName(library.getPackage());
libInfo.setDescription(library.getDescription());
libInfo.setQName(library.getQName().toString());
libInfo.setStatus(library.getLibStatus());
librarySet.add(libInfo);
}
return librarySet.toArray(new LibraryInfo[libraries.size()]);
}
private void handleException(Log log, String message, Exception e) throws AxisFault {
if (e == null) {
AxisFault exception = new AxisFault(message);
log.error(message, exception);
throw exception;
} else {
message = message + " :: " + e.getMessage();
log.error(message, e);
throw new AxisFault(message, e);
}
}
/**
* Creates an <code>OMElement</code> from the given string
*
* @param str
* the XML string
* @return the <code>OMElement</code> representation of the given string
* @throws javax.xml.stream.XMLStreamException
* if building the <code>OmElement</code> is unsuccessful
*/
private OMElement createElement(String str) throws XMLStreamException {
InputStream in = new ByteArrayInputStream(str.getBytes());
return new StAXOMBuilder(in).getDocumentElement();
}
private static String getTenantIdString(AxisConfiguration axisConfig) {
return String.valueOf(getTenantId(axisConfig));
}
private static int getTenantId(AxisConfiguration axisConfig) {
PrivilegedCarbonContext carbonContext =
PrivilegedCarbonContext.getThreadLocalCarbonContext();
return carbonContext.getTenantId();
}
/**
* Used to download a carbon application archive.
*
* @param fileName
* the name of the application archive (.car) to be downloaded
* @return datahandler corresponding to the .car file to be downloaded
* @throws Exception
* for invalid scenarios
*/
public DataHandler downloadLibraryArchive(String fileName) throws Exception {
// CarbonApplication instance to delete
Library currentMediationLib = null;
// Iterate all applications for this tenant and find the application to
// delete
SynapseConfiguration synConfigForTenant = getSynapseConfiguration();
Collection<Library> appList = synConfigForTenant.getSynapseLibraries().values();
for (Library mediationLib : appList) {
if (fileName.equals(mediationLib.getQName().getLocalPart().toString())) {
currentMediationLib = mediationLib;
}
}
FileDataSource datasource = new FileDataSource(new File(currentMediationLib.getFileName()));
DataHandler handler = new DataHandler(datasource);
return handler;
}
/**
* Performing the action of enabling/disabling the given meidation library
*
* @param libName
* @param packageName
* @param status
* @throws AxisFault
*/
public boolean updateStatus(String libQName, String libName, String packageName, String status)
throws AxisFault {
try {
SynapseConfiguration configuration = getSynapseConfiguration();
SynapseImport synapseImport = configuration.getSynapseImports().get(libQName);
if (synapseImport == null && libName != null && packageName != null) {
addImport(libName, packageName);
synapseImport = configuration.getSynapseImports().get(libQName);
}
Library synLib = getSynapseConfiguration().getSynapseLibraries().get(libQName);
if (libQName != null && synLib != null) {
if (ServiceBusConstants.ENABLED.equals(status)) {
synapseImport.setStatus(true);
synLib.setLibStatus(true);
synLib.loadLibrary();
deployingLocalEntries(synLib, configuration);
} else {
synapseImport.setStatus(false);
synLib.setLibStatus(false);
synLib.unLoadLibrary();
undeployingLocalEntries(synLib, configuration);
}
// update synapse configuration.
MediationPersistenceManager mp = getMediationPersistenceManager();
mp.saveItem(synapseImport.getName(), ServiceBusConstants.ITEM_TYPE_IMPORT);
}
} catch (Exception e) {
String message = "Unable to update status for : " + libQName;
handleException(log, message, e);
}
return true;
}
/**
* Deploy the local entries from lib
*
* */
private void deployingLocalEntries(Library library, SynapseConfiguration config) {
if (log.isDebugEnabled()) {
log.debug("Start : Adding Local registry entries to the configuration");
}
for (Map.Entry<String, Object> libararyEntryMap : library.getLocalEntryArtifacts()
.entrySet()) {
File localEntryFileObj = (File) libararyEntryMap.getValue();
OMElement document = LocalEntryUtil.getOMElement(localEntryFileObj);
addEntry(document.toString());
}
if (log.isDebugEnabled()) {
log.debug("End : Adding Local registry entries to the configuration");
}
}
/**
*
* Undeploy the local entries deployed from the lib
*
* */
private void undeployingLocalEntries(Library library, SynapseConfiguration config) {
if (log.isDebugEnabled()) {
log.debug("Start : Removing Local registry entries from the configuration");
}
for (Map.Entry<String, Object> libararyEntryMap : library.getLocalEntryArtifacts()
.entrySet()) {
File localEntryFileObj = (File) libararyEntryMap.getValue();
OMElement document = LocalEntryUtil.getOMElement(localEntryFileObj);
deleteEntry(document.toString());
}
if (log.isDebugEnabled()) {
log.debug("End : Removing Local registry entries from the configuration");
}
}
/**
* Add the local entry
*
* */
private boolean addEntry(String ele) {
final Lock lock = getLock();
try {
lock.lock();
OMElement elem;
try {
elem = LocalEntryUtil.nonCoalescingStringToOm(ele);
} catch (XMLStreamException e) {
log.error("Error while converting the file content : " + e.getMessage());
return false;
}
if (elem.getQName().getLocalPart().equals(XMLConfigConstants.ENTRY_ELT.getLocalPart())) {
String entryKey = elem.getAttributeValue(new QName("key"));
entryKey = entryKey.trim();
if (log.isDebugEnabled()) {
log.debug("Adding local entry with key : " + entryKey);
}
if (getSynapseConfiguration().getLocalRegistry().containsKey(entryKey)) {
log.error("An Entry with key " + entryKey +
" is already used within the configuration");
} else {
Entry entry =
EntryFactory.createEntry(elem,
getSynapseConfiguration().getProperties());
entry.setFileName(ServiceBusUtils.generateFileName(entry.getKey()));
getSynapseConfiguration().addEntry(entryKey, entry);
MediationPersistenceManager pm =
ServiceBusUtils.getMediationPersistenceManager(getAxisConfig());
pm.saveItem(entry.getKey(), ServiceBusConstants.ITEM_TYPE_ENTRY);
}
if (log.isDebugEnabled()) {
log.debug("Local registry entry : " + entryKey + " added to the configuration");
}
return true;
} else {
log.warn("Error adding local entry. Invalid definition");
}
} catch (SynapseException syne) {
log.error("Unable to add local entry ", syne);
} catch (OMException e) {
log.error("Unable to add local entry. Invalid XML ", e);
} catch (Exception e) {
log.error("Unable to add local entry. Invalid XML ", e);
} finally {
lock.unlock();
}
return false;
}
/**
* Remove the local entry
* */
public boolean deleteEntry(String ele) {
final Lock lock = getLock();
String entryKey = null;
try {
lock.lock();
OMElement elem;
try {
elem = LocalEntryUtil.nonCoalescingStringToOm(ele);
} catch (XMLStreamException e) {
log.error("Error while converting the file content : " + e.getMessage());
return false;
}
if (elem.getQName().getLocalPart().equals(XMLConfigConstants.ENTRY_ELT.getLocalPart())) {
entryKey = elem.getAttributeValue(new QName("key"));
entryKey = entryKey.trim();
log.debug("Adding local entry with key : " + entryKey);
SynapseConfiguration synapseConfiguration = getSynapseConfiguration();
Entry entry = synapseConfiguration.getDefinedEntries().get(entryKey);
if (entry != null) {
synapseConfiguration.removeEntry(entryKey);
MediationPersistenceManager pm =
ServiceBusUtils.getMediationPersistenceManager(getAxisConfig());
pm.deleteItem(entryKey, entry.getFileName(),
ServiceBusConstants.ITEM_TYPE_ENTRY);
if (log.isDebugEnabled()) {
log.debug("Deleted local entry with key : " + entryKey);
}
return true;
} else {
log.warn("No entry exists by the key : " + entryKey);
return false;
}
}
} catch (SynapseException syne) {
log.error("Unable to delete the local entry : " + entryKey, syne);
} catch (Exception e) {
log.error("Unable to delete the local entry : " + entryKey, e);
} finally {
lock.unlock();
}
return false;
}
}