/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.nbstudio.project;
import com.intersys.objects.CacheDatabase;
import com.intersys.objects.CacheException;
import com.intersys.objects.CacheQuery;
import com.intersys.objects.Database;
import java.awt.Component;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;
import java.util.zip.ZipInputStream;
import javax.swing.JComponent;
import javax.swing.event.ChangeListener;
import org.netbeans.api.templates.TemplateRegistration;
import org.netbeans.spi.project.ui.support.ProjectChooser;
import org.netbeans.spi.project.ui.templates.support.Templates;
import org.openide.WizardDescriptor;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle.Messages;
@TemplateRegistration(
folder = "Project/MUMPS",
content = "CacheProject.zip",
displayName = "#CacheProjectWizardIterator_displayName",
iconBase = "org/nbstudio/project/project.gif",
targetName = "CacheProject",
description = "CacheProject.html")
@Messages("CacheProjectWizardIterator_displayName=InterSystems Caché")
public final class CacheProjectWizardIterator implements WizardDescriptor.InstantiatingIterator<WizardDescriptor> {
private int index;
private WizardDescriptor wizard;
private List<WizardDescriptor.Panel<WizardDescriptor>> panels;
private List<WizardDescriptor.Panel<WizardDescriptor>> getPanels() {
if (panels == null) {
panels = new ArrayList<>();
panels.add(new CacheProjectWizardPanel1());
panels.add(new CacheProjectWizardPanel2());
String[] steps = createSteps();
for (int i = 0; i < panels.size(); i++) {
Component c = panels.get(i).getComponent();
if (steps[i] == null) {
// Default step name to component name of panel. Mainly
// useful for getting the name of the target chooser to
// appear in the list of steps.
steps[i] = c.getName();
}
if (c instanceof JComponent) { // assume Swing components
JComponent jc = (JComponent) c;
jc.putClientProperty(WizardDescriptor.PROP_CONTENT_SELECTED_INDEX, i);
jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DATA, steps);
jc.putClientProperty(WizardDescriptor.PROP_AUTO_WIZARD_STYLE, true);
jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DISPLAYED, true);
jc.putClientProperty(WizardDescriptor.PROP_CONTENT_NUMBERED, true);
}
}
}
return panels;
}
@Override
public Set<?> instantiate() throws IOException {
Set<FileObject> resultSet = new LinkedHashSet<>();
File dirF = FileUtil.normalizeFile((File) wizard.getProperty("projdir"));
dirF.mkdirs();
Properties propsProject = new Properties();
propsProject.setProperty("server.addr", (String) wizard.getProperty("addr"));
propsProject.setProperty("server.port", (String) wizard.getProperty("port"));
propsProject.setProperty("server.namespace", (String) wizard.getProperty("namespace"));
String cacheProjectName = (String) wizard.getProperty("cacheProjectName");
propsProject.setProperty("server.project", (cacheProjectName == null) ? "" : cacheProjectName);
propsProject.setProperty("server.login", (String) wizard.getProperty("login"));
propsProject.setProperty("server.pass", (String) wizard.getProperty("pass"));
FileObject template = Templates.getTemplate(wizard);
FileObject dir = FileUtil.toFileObject(dirF);
unZipFile(template.getInputStream(), dir, propsProject);
resultSet.add(dir);
File parent = dirF.getParentFile();
if (parent != null && parent.exists()) {
ProjectChooser.setProjectsFolder(parent);
}
return resultSet;
}
@Override
public void initialize(WizardDescriptor wizard) {
this.wizard = wizard;
wizard.putProperty("WizardPanel_TestConnectionError", "");
}
@Override
public void uninitialize(WizardDescriptor wizard) {
panels = null;
}
@Override
public WizardDescriptor.Panel<WizardDescriptor> current() {
return getPanels().get(index);
}
@Override
public String name() {
return index + 1 + ". from " + getPanels().size();
}
@Override
public boolean hasNext() {
return index < getPanels().size() - 1;
}
@Override
public boolean hasPrevious() {
return index > 0;
}
@Override
public void nextPanel() {
if ((index == 0) && (!testConnection())) {
return;
}
if (!hasNext()) {
throw new NoSuchElementException();
}
index++;
}
public static Database getConnection(WizardDescriptor wizard, String nsp) throws CacheException {
String addr = (String) wizard.getProperty("addr");
String port = (String) wizard.getProperty("port");
String login = (String) wizard.getProperty("login");
String pass = (String) wizard.getProperty("pass");
String connString = "jdbc:Cache://" + addr + ":" + port + "/" + nsp;
pass = (pass.isEmpty() && login.isEmpty()) ? "SYS" : pass;
login = login.isEmpty() ? "_SYSTEM" : login;
return CacheDatabase.getLightDatabase(connString, login, pass);
}
boolean testConnection() {
wizard.putProperty("WizardPanel_TestConnectionError", "");
Database conn = null;
try {
conn = getConnection(wizard, "%SYS");
CacheQuery query = new CacheQuery(conn, "%SYS.Namespace", "List");
ResultSet rs = query.execute();
List<String> nspList = new ArrayList<>();
while (rs.next()) {
String nsp = rs.getString("Nsp");
nspList.add(nsp);
}
wizard.putProperty("WizardPanel_NSPList", nspList);
} catch (CacheException ex) {
String message = ex.getLocalizedMessage();
String[] messages = message.split("\\[Cache JDBC\\]");
message = messages[messages.length - 1];
wizard.putProperty("WizardPanel_TestConnectionError", message);
return false;
} catch (SQLException ex) {
Exceptions.printStackTrace(ex);
wizard.putProperty("WizardPanel_TestConnectionError", ex.getLocalizedMessage());
return false;
} finally {
if (conn != null && conn.isOpen()) {
try {
conn.close();
} catch (CacheException ex) {
}
}
}
return true;
}
@Override
public void previousPanel() {
if (!hasPrevious()) {
throw new NoSuchElementException();
}
index--;
}
// If nothing unusual changes in the middle of the wizard, simply:
@Override
public void addChangeListener(ChangeListener l) {
}
@Override
public void removeChangeListener(ChangeListener l) {
}
// If something changes dynamically (besides moving between panels), e.g.
// the number of panels changes in response to user input, then use
// ChangeSupport to implement add/removeChangeListener and call fireChange
// when needed
// You could safely ignore this method. Is is here to keep steps which were
// there before this wizard was instantiated. It should be better handled
// by NetBeans Wizard API itself rather than needed to be implemented by a
// client code.
private String[] createSteps() {
String[] beforeSteps = (String[]) wizard.getProperty("WizardPanel_contentData");
assert beforeSteps != null : "This wizard may only be used embedded in the template wizard";
String[] res = new String[(beforeSteps.length - 1) + panels.size()];
for (int i = 0; i < res.length; i++) {
if (i < (beforeSteps.length - 1)) {
res[i] = beforeSteps[i];
} else {
res[i] = panels.get(i - beforeSteps.length + 1).getComponent().getName();
}
}
return res;
}
private static void unZipFile(InputStream source, FileObject projectRoot, Properties props) throws IOException {
try {
ZipInputStream str = new ZipInputStream(source);
ZipEntry entry;
while ((entry = str.getNextEntry()) != null) {
if (entry.isDirectory()) {
FileUtil.createFolder(projectRoot, entry.getName());
} else {
FileObject fo = FileUtil.createData(projectRoot, entry.getName());
if ("cacheProject.properties".equals(entry.getName())) {
// Special handling for setting properties
filterProjectProperties(fo, str, props);
} else {
writeFile(str, fo);
}
}
}
} finally {
source.close();
}
}
private static void writeFile(ZipInputStream str, FileObject fo) throws IOException {
try (OutputStream out = fo.getOutputStream()) {
FileUtil.copy(str, out);
}
}
private static void filterProjectProperties(FileObject fo, ZipInputStream str, Properties props) throws IOException {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileUtil.copy(str, baos);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
Properties propsOriginal = new Properties();
propsOriginal.load(bais);
Properties propsProject = new Properties();
propsProject.putAll(propsOriginal);
propsProject.putAll(props);
try (OutputStream out = fo.getOutputStream()) {
propsProject.store(out, "Caché Project Properties File");
}
} catch (Exception ex) {
Exceptions.printStackTrace(ex);
writeFile(str, fo);
}
}
}