blob: b71041e681943e8a22d436de12c6d4666ec4def0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.netbeans.modules.javaee.wildfly.config;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.modules.j2ee.deployment.common.api.ConfigurationException;
import org.netbeans.modules.j2ee.deployment.common.api.Datasource;
import org.netbeans.modules.j2ee.deployment.common.api.DatasourceAlreadyExistsException;
import org.netbeans.modules.j2ee.deployment.plugins.api.InstanceProperties;
import org.netbeans.modules.j2ee.deployment.plugins.spi.DatasourceManager;
import org.netbeans.modules.javaee.wildfly.WildflyDeploymentManager;
import org.netbeans.modules.javaee.wildfly.config.ds.gen.DatasourceType;
import org.netbeans.modules.javaee.wildfly.config.ds.gen.Datasources;
import org.netbeans.modules.javaee.wildfly.config.ds.gen.DsSecurityType;
import org.netbeans.modules.javaee.wildfly.config.ds.gen.PoolType;
import org.netbeans.modules.javaee.wildfly.config.xml.ConfigurationParser;
import org.netbeans.modules.javaee.wildfly.ide.ui.WildflyPluginProperties;
import org.netbeans.modules.schema2beans.BaseBean;
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
/**
*
* @author Libor Kotouc
* @author Emmanuel Hugonnet (ehsavoie) <ehsavoie@netbeans.org>
*/
public final class WildflyDatasourceManager implements DatasourceManager {
private static final Logger LOGGER = Logger.getLogger(WildflyDatasourceManager.class.getName());
private static final String DSdotXML = "-ds.xml"; // NOI18N
private static final String JBossDSdotXML = "jboss-ds.xml"; // NOI18N
private final FileObject deployDir;
private final FileObject configFile;
private final WildflyDeploymentManager dm;
public WildflyDatasourceManager(WildflyDeploymentManager dm) {
this.dm = dm;
InstanceProperties ip = InstanceProperties.getInstanceProperties(dm.getUrl());
String deployDirPath = ip.getProperty(WildflyPluginProperties.PROPERTY_DEPLOY_DIR);
deployDir = FileUtil.toFileObject(new File(deployDirPath));
String configFilePath = ip.getProperty(WildflyPluginProperties.PROPERTY_CONFIG_FILE);
if(configFilePath != null) {
File config = new File(configFilePath);
if(config.exists()) {
configFile = FileUtil.toFileObject(config);
} else {
throw new IllegalArgumentException("No configuration file found: " + configFilePath);
}
} else {
throw new IllegalArgumentException("No configuration file configured: " + dm);
}
}
@Override
public Set<Datasource> getDatasources() throws ConfigurationException {
return ConfigurationParser.INSTANCE.listDatasources(configFile);
}
@Override
public void deployDatasources(Set<Datasource> datasources)
throws ConfigurationException, DatasourceAlreadyExistsException {
Set<Datasource> deployedDS = getDatasources();
Map<String, Datasource> ddsMap = transform(deployedDS); // for faster searching
HashMap<String, Datasource> newDS = new HashMap<String, Datasource>(); // will contain all ds which do not conflict with existing ones
//resolve all conflicts
LinkedList<Datasource> conflictDS = new LinkedList<Datasource>();
for (Iterator<Datasource> it = datasources.iterator(); it.hasNext();) {
Object o = it.next();
if (!(o instanceof WildflyDatasource)) {
continue;
}
WildflyDatasource ds = (WildflyDatasource) o;
String jndiName = WildflyDatasource.getRawName(ds.getJndiName());
if (ddsMap.keySet().contains(jndiName)) { // conflicting ds found
if (!ddsMap.get(jndiName).equals(ds)) { // found ds is not equal
conflictDS.add(ddsMap.get(jndiName)); // NOI18N
}
} else if (jndiName != null) {
newDS.put(jndiName, ds);
}
}
if (conflictDS.size() > 0) { // conflict found -> exception
throw new DatasourceAlreadyExistsException(conflictDS);
}
//write jboss-ds.xml
FileObject dsXmlFo = deployDir.getFileObject(JBossDSdotXML);
File dsXMLFile = (dsXmlFo != null ? FileUtil.toFile(dsXmlFo) : null);
Datasources deployedDSGraph = null;
try {
deployedDSGraph = (dsXMLFile != null ? Datasources.createGraph(dsXMLFile) : new Datasources());
} catch (IOException ioe) {
Exceptions.attachLocalizedMessage(ioe, NbBundle.getMessage(getClass(), "ERR_CannotReadDSdotXml"));
Logger.getLogger("global").log(Level.INFO, null, ioe);
return;
}
//merge ds graph with newDS - remove conflicting ds from graph
DatasourceType ltxds[] = deployedDSGraph.getDatasource();
for (int i = 0; i < ltxds.length; i++) {
String jndiName = ltxds[i].getJndiName();
if (newDS.keySet().contains(jndiName)) //conflict, we must remove it from graph
{
deployedDSGraph.removeDatasource(ltxds[i]);
}
}
//add all ds from newDS
for (Iterator it = newDS.values().iterator(); it.hasNext();) {
WildflyDatasource ds = (WildflyDatasource) it.next();
DatasourceType lds = new DatasourceType();
lds.setJndiName(WildflyDatasource.getRawName(ds.getJndiName()));
lds.setConnectionUrl(ds.getUrl());
lds.setDriverClass(ds.getDriverClassName());
DsSecurityType security = new DsSecurityType();
security.setUserName(ds.getUsername());
security.setPassword(ds.getPassword());
lds.setSecurity(security);
PoolType pool = new PoolType();
pool.setMinPoolSize(Long.parseLong(ds.getMinPoolSize()));
pool.setMaxPoolSize(Long.parseLong(ds.getMaxPoolSize()));
lds.setPool(pool);
String poolName = ds.getJndiName();
int index = ds.getJndiName().lastIndexOf('/');
if(index > 0) {
poolName = ds.getJndiName().substring(index);
}
lds.setPoolName(poolName);
deployedDSGraph.addDatasource(lds);
}
//write modified graph into jboss-ds.xml
if (newDS.size() > 0) {
if (dsXMLFile == null) {
try {
dsXmlFo = deployDir.createData(JBossDSdotXML);
} catch (IOException ioe) {
Exceptions.attachLocalizedMessage(ioe, NbBundle.getMessage(getClass(), "ERR_CannotCreateDSdotXml"));
Logger.getLogger("global").log(Level.INFO, null, ioe);
return;
}
dsXMLFile = FileUtil.toFile(dsXmlFo);
}
writeFile(dsXMLFile, deployedDSGraph);
}
}
private Map<String, Datasource> transform(Set<Datasource> datasources) {
HashMap<String, Datasource> map = new HashMap<String, Datasource>();
for (Iterator it = datasources.iterator(); it.hasNext();) {
WildflyDatasource ds = (WildflyDatasource) it.next();
if (ds.getJndiName() != null) {
map.put(ds.getJndiName(), ds);
}
}
return map;
}
private void writeFile(final File file, final BaseBean bean) throws ConfigurationException {
try {
FileSystem fs = deployDir.getFileSystem();
fs.runAtomicAction(new FileSystem.AtomicAction() {
public void run() throws IOException {
OutputStream os = null;
FileLock lock = null;
try {
String name = file.getName();
FileObject configFO = deployDir.getFileObject(name);
if (configFO == null) {
configFO = deployDir.createData(name);
}
lock = configFO.lock();
os = new BufferedOutputStream(configFO.getOutputStream(lock), 4096);
// TODO notification needed
if (bean != null) {
bean.write(os);
}
} finally {
if (os != null) {
try {
os.close();
} catch (IOException ioe) {
}
}
if (lock != null) {
lock.releaseLock();
}
}
}
});
} catch (IOException e) {
throw new ConfigurationException(e.getLocalizedMessage());
}
}
}