/*
 * 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.javafx2.project;

import java.awt.Color;
import java.awt.Component;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URL;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableModel;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.platform.JavaPlatform;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.java.project.classpath.ProjectClassPathModifier;
import org.netbeans.api.java.queries.SourceForBinaryQuery;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.ant.AntArtifact;
import org.netbeans.api.project.ant.AntArtifactQuery;
import org.netbeans.modules.java.api.common.project.ProjectProperties;
import org.netbeans.modules.java.j2seproject.api.J2SEPropertyEvaluator;
import org.netbeans.modules.javafx2.platform.api.JavaFXPlatformUtils;
import org.netbeans.modules.javafx2.project.ui.JFXApplicationPanel;
import org.netbeans.modules.javafx2.project.ui.JFXPackagingPanel;
import org.netbeans.modules.javafx2.project.ui.JSEDeploymentPanel;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.netbeans.spi.project.support.ant.EditableProperties;
import org.netbeans.spi.project.support.ant.PropertyEvaluator;
import org.netbeans.spi.project.support.ant.PropertyUtils;
import org.netbeans.spi.project.support.ant.ui.StoreGroup;
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.Mutex;
import org.openide.util.MutexException;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;

public final class JFXProjectProperties {

    private static final Logger LOG = Logger.getLogger(JFXProjectProperties.class.getName());
    private static final Color INVALID_CELL_CONTENT_COLOR = Color.RED;
    
    public static final String JAVAFX_ENABLED = "javafx.enabled"; // NOI18N
    public static final String JAVAFX_PRELOADER = "javafx.preloader"; // NOI18N
    public static final String JAVAFX_SWING = "javafx.swing"; // NOI18N
    public static final String JAVAFX_DISABLE_AUTOUPDATE = "javafx.disable.autoupdate"; // NOI18N
    public static final String JAVAFX_DISABLE_AUTOUPDATE_NOTIFICATION = "javafx.disable.autoupdate.notification"; // NOI18N
    public static final String JAVAFX_DISABLE_CONCURRENT_RUNS = "javafx.disable.concurrent.runs"; // NOI18N
    public static final String JAVAFX_ENABLE_CONCURRENT_EXTERNAL_RUNS = "javafx.enable.concurrent.external.runs"; // NOI18N
    public static final String JAVAFX_ENDORSED_ANT_CLASSPATH = "endorsed.javafx.ant.classpath"; // NOI18N
    public static final String PLATFORM_ACTIVE = "platform.active"; // NOI18N
    public static final String PLATFORM_ANT_NAME = "platform.ant.name";    //NOI18N
    
    /** The standard extension for FXML source files. */
    public static final String FXML_EXTENSION = "fxml"; // NOI18N    
    
    // copies of private J2SE properties
    public static final String SOURCE_ENCODING = "source.encoding"; // NOI18N
    public static final String JAVADOC_PRIVATE = "javadoc.private"; // NOI18N
    public static final String JAVADOC_NO_TREE = "javadoc.notree"; // NOI18N
    public static final String JAVADOC_USE = "javadoc.use"; // NOI18N
    public static final String JAVADOC_NO_NAVBAR = "javadoc.nonavbar"; // NOI18N
    public static final String JAVADOC_NO_INDEX = "javadoc.noindex"; // NOI18N
    public static final String JAVADOC_SPLIT_INDEX = "javadoc.splitindex"; // NOI18N
    public static final String JAVADOC_AUTHOR = "javadoc.author"; // NOI18N
    public static final String JAVADOC_VERSION = "javadoc.version"; // NOI18N
    public static final String JAVADOC_WINDOW_TITLE = "javadoc.windowtitle"; // NOI18N
    public static final String JAVADOC_ENCODING = "javadoc.encoding"; // NOI18N
    public static final String JAVADOC_ADDITIONALPARAM = "javadoc.additionalparam"; // NOI18N
    public static final String BUILD_SCRIPT = "buildfile"; //NOI18N
    public static final String DIST_JAR = "dist.jar"; // NOI18N

    // Packaging properties
    public static final String JAVAFX_BINARY_ENCODE_CSS = "javafx.binarycss"; // NOI18N
    public static final String JAVAFX_DEPLOY_INCLUDEDT = "javafx.deploy.includeDT"; // NOI18N
    public static final String JAVAFX_DEPLOY_EMBEDJNLP = "javafx.deploy.embedJNLP"; // NOI18N
    public static final String JAVAFX_REBASE_LIBS = "javafx.rebase.libs"; // NOI18N
    
    // FX config properties (Run panel), replicated from ProjectProperties
    public static final String MAIN_CLASS = "javafx.main.class"; // NOI18N
    //public static final String APPLICATION_ARGS = JFXProjectConfigurations.APPLICATION_ARGS;
    //public static final String APP_PARAM_PREFIX = JFXProjectConfigurations.APP_PARAM_PREFIX;
    //public static final String APP_PARAM_SUFFIXES[] = JFXProjectConfigurations.APP_PARAM_SUFFIXES;
    public static final String RUN_JVM_ARGS = ProjectProperties.RUN_JVM_ARGS;
    public static final String FALLBACK_CLASS = "javafx.fallback.class"; // NOI18N
    public static final String SIGNED_JAR = "dist.signed.jar"; // NOI18N
    
    public static final String PRELOADER_ENABLED = "javafx.preloader.enabled"; // NOI18N
    public static final String PRELOADER_TYPE = "javafx.preloader.type"; // NOI18N
    public static final String PRELOADER_PROJECT = "javafx.preloader.project.path"; // NOI18N
    public static final String PRELOADER_CLASS = "javafx.preloader.class"; // NOI18N
    public static final String PRELOADER_JAR_FILENAME = "javafx.preloader.jar.filename"; // NOI18N
    public static final String PRELOADER_JAR_PATH = "javafx.preloader.jar.path"; // NOI18N
    
    public static final String RUN_WORK_DIR = ProjectProperties.RUN_WORK_DIR; // NOI18N
    public static final String RUN_APP_WIDTH = "javafx.run.width"; // NOI18N
    public static final String RUN_APP_HEIGHT = "javafx.run.height"; // NOI18N
    public static final String RUN_IN_HTMLTEMPLATE = "javafx.run.htmltemplate"; // NOI18N
    public static final String RUN_IN_HTMLTEMPLATE_PROCESSED = "javafx.run.htmltemplate.processed"; // NOI18N
    public static final String RUN_IN_BROWSER = "javafx.run.inbrowser"; // NOI18N
    public static final String RUN_IN_BROWSER_PATH = "javafx.run.inbrowser.path"; // NOI18N
    public static final String RUN_IN_BROWSER_ARGUMENTS = "javafx.run.inbrowser.arguments"; // NOI18N
    public static final String RUN_IN_BROWSER_UNDEFINED = "undefined"; // NOI18N
    public static final String RUN_AS = "javafx.run.as"; // NOI18N

    public static final String DEFAULT_APP_WIDTH = "800"; // NOI18N
    public static final String DEFAULT_APP_HEIGHT = "600"; // NOI18N

    // Deployment properties
    public static final String UPDATE_MODE_BACKGROUND = "javafx.deploy.backgroundupdate"; // NOI18N
    public static final String ALLOW_OFFLINE = "javafx.deploy.allowoffline"; // NOI18N
    public static final String INSTALL_PERMANENTLY = "javafx.deploy.installpermanently"; // NOI18N
    public static final String ADD_DESKTOP_SHORTCUT = "javafx.deploy.adddesktopshortcut"; // NOI18N
    public static final String ADD_STARTMENU_SHORTCUT = "javafx.deploy.addstartmenushortcut"; // NOI18N
    public static final String ICON_FILE = "javafx.deploy.icon"; // NOI18N
    public static final String NATIVE_ICON_FILE = "javafx.deploy.icon.native"; // NOI18N
    public static final String SPLASH_IMAGE_FILE = "javafx.deploy.splash"; // NOI18N
    public static final String PERMISSIONS_ELEVATED = "javafx.deploy.permissionselevated"; // NOI18N
    public static final String DISABLE_PROXY = "javafx.deploy.disable.proxy"; // NOI18N
    public static final String REQUEST_RT = "javafx.deploy.request.runtime"; // NOI18N

    // Deployment - signing
    public static final String JAVAFX_SIGNING_ENABLED = "javafx.signing.enabled"; //NOI18N
    public static final String JAVAFX_SIGNING_TYPE = "javafx.signing.type"; //NOI18N
    public static final String JAVAFX_SIGNING_KEYSTORE = "javafx.signing.keystore"; //NOI18N
    public static final String JAVAFX_SIGNING_KEYSTORE_PASSWORD = "javafx.signing.keystore.password"; //NOI18N
    public static final String JAVAFX_SIGNING_KEY = "javafx.signing.keyalias"; //NOI18N
    public static final String JAVAFX_SIGNING_KEY_PASSWORD = "javafx.signing.keyalias.password"; //NOI18N
    public static final String JAVAFX_SIGNING_BLOB = "javafx.signing.blob"; //NOI18N
    
    // Deployment - native packaging
    public static final String NATIVE_BUNDLING_ENABLED = "native.bundling.enabled"; //NOI18N
    public static final String NATIVE_BUNDLING_TYPE = "native.bundling.type"; //NOI18N
    //public static final String JAVASE_NATIVE_BUNDLING_ENABLED = "native.bundling.enabled"; //NOI18N

    //Deloyment - copylibs
    public static final String COPYLIBS_EXCLUDES = "copylibs.excludes"; //NOI18N

    // Deployment - common and SE specific
    public static final String RUN_CP = "run.classpath";    //NOI18N
    public static final String BUILD_CLASSES = "build.classes.dir"; //NOI18N
    public static final String JAVASE_KEEP_JFXRT_ON_CLASSPATH = "keep.javafx.runtime.on.classpath"; //NOI18N
    
    // Deployment - libraries download mode
    public static final String DOWNLOAD_MODE_LAZY_JARS = "download.mode.lazy.jars";   //NOI18N
    private static final String DOWNLOAD_MODE_LAZY_JAR = "download.mode.lazy.jar."; //NOI18N
    private static final String DOWNLOAD_MODE_LAZY_FORMAT = DOWNLOAD_MODE_LAZY_JAR +"%s"; //NOI18N
    
    // Deployment - callbacks
    public static final String JAVASCRIPT_CALLBACK_PREFIX = "javafx.jscallback."; // NOI18N
    
    // Application
    public static final String IMPLEMENTATION_VERSION = "javafx.application.implementation.version"; // NOI18N
    public static final String IMPLEMENTATION_VERSION_DEFAULT = "1.0"; // NOI18N
    
    // folders and files
    public static final String PROJECT_CONFIGS_DIR = JFXProjectConfigurations.PROJECT_CONFIGS_DIR;
    public static final String PROJECT_PRIVATE_CONFIGS_DIR = JFXProjectConfigurations.PROJECT_PRIVATE_CONFIGS_DIR;
    public static final String PROPERTIES_FILE_EXT = JFXProjectConfigurations.PROPERTIES_FILE_EXT;
    public static final String CONFIG_PROPERTIES_FILE = JFXProjectConfigurations.CONFIG_PROPERTIES_FILE;
    public static final String DEFAULT_CONFIG = NbBundle.getBundle("org.netbeans.modules.javafx2.project.ui.Bundle").getString("JFXConfigurationProvider.default.label"); // NOI18N
    public static final String DEFAULT_CONFIG_STANDALONE = NbBundle.getBundle("org.netbeans.modules.javafx2.project.ui.Bundle").getString("JFXConfigurationProvider.standalone.label"); // NOI18N
    public static final String DEFAULT_CONFIG_WEBSTART = NbBundle.getBundle("org.netbeans.modules.javafx2.project.ui.Bundle").getString("JFXConfigurationProvider.webstart.label"); // NOI18N
    public static final String DEFAULT_CONFIG_BROWSER = NbBundle.getBundle("org.netbeans.modules.javafx2.project.ui.Bundle").getString("JFXConfigurationProvider.browser.label"); // NOI18N

    // explicit manifest entries (see #231951, #234231, http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/no_redeploy.html)
    public static final String MANIFEST_CUSTOM_CODEBASE = "manifest.custom.codebase"; // NOI18N
    public static final String MANIFEST_CUSTOM_PERMISSIONS = "manifest.custom.permissions"; // NOI18N
    public static final String PLATFORM_RUNTIME = "platform.runtime";           //NOI18N
    
    // FX RT artifact reference to be kept at compile classpath
    private static final String JFX_EXTENSION_CPREF = "${javafx.classpath.extension}";  //NOI18N

    private StoreGroup fxPropGroup = new StoreGroup();
    
    // Packaging
    JToggleButton.ToggleButtonModel binaryEncodeCSS;
    public JToggleButton.ToggleButtonModel getBinaryEncodeCSSModel() {
        return binaryEncodeCSS;
    }

    private JFXPackagingPanel packagingPanel = null;
    public JFXPackagingPanel getPackagingPanel() {
        if(packagingPanel == null) {
            packagingPanel = new JFXPackagingPanel(this);
        }
        return packagingPanel;
    }

    private JFXApplicationPanel applicationPanel = null;
    public JFXApplicationPanel getApplicationPanel() {
        if(applicationPanel == null) {
            applicationPanel = new JFXApplicationPanel(this);
        }
        return applicationPanel;
    }

    private JSEDeploymentPanel seDeploymentPanel = null;
    public JSEDeploymentPanel getSEDeploymentPanel() {
        if(seDeploymentPanel == null) {
            seDeploymentPanel = new JSEDeploymentPanel(this);
        }
        return seDeploymentPanel;
    }

    // CustomizerRun
    private JFXConfigs CONFIGS = null;
    public JFXConfigs getConfigs() {
        return CONFIGS;
    }

    private Map<String,String> browserPaths = null;

    public Map<String, String> getBrowserPaths() {
        return browserPaths;
    }
    public void resetBrowserPaths() {
        this.browserPaths = new HashMap<String, String>();
    }
    public void setBrowserPaths(Map<String, String> browserPaths) {
        this.browserPaths = browserPaths;
    }

    // CustomizerRun - Preloader source type
    public enum PreloaderSourceType {
        NONE("none"), // NOI18N
        PROJECT("project"), // NOI18N
        JAR("jar"); // NOI18N
        private final String propertyValue;
        PreloaderSourceType(String propertyValue) {
            this.propertyValue = propertyValue;
        }
        public String getString() {
            return propertyValue;
        }
    }
    
    PreloaderClassComboBoxModel preloaderClassModel;
    public PreloaderClassComboBoxModel getPreloaderClassModel() {
        return preloaderClassModel;
    }

    // CustomizerRun - Run type
    public enum RunAsType {
        STANDALONE("standalone", DEFAULT_CONFIG_STANDALONE), // NOI18N
        ASWEBSTART("webstart", DEFAULT_CONFIG_WEBSTART), // NOI18N
        INBROWSER("embedded", DEFAULT_CONFIG_BROWSER); // NOI18N
        private final String propertyValue;
        private final String defaultConfig;
        RunAsType(String propertyValue, String defaultConfig) {
            this.propertyValue = propertyValue;
            this.defaultConfig = defaultConfig;
        }
        public String getString() {
            return propertyValue;
        }
        public String getDefaultConfig() {
            return defaultConfig;
        }
    }
    JToggleButton.ToggleButtonModel runStandalone;
    JToggleButton.ToggleButtonModel runAsWebStart;
    JToggleButton.ToggleButtonModel runInBrowser;
    
    // Deployment
    JToggleButton.ToggleButtonModel allowOfflineModel;
    public JToggleButton.ToggleButtonModel getAllowOfflineModel() {
        return allowOfflineModel;
    }
    JToggleButton.ToggleButtonModel backgroundUpdateCheck;
    public JToggleButton.ToggleButtonModel getBackgroundUpdateCheckModel() {
        return backgroundUpdateCheck;
    }
    JToggleButton.ToggleButtonModel installPermanently;
    public JToggleButton.ToggleButtonModel getInstallPermanentlyModel() {
        return installPermanently;
    }
    JToggleButton.ToggleButtonModel addDesktopShortcut;
    public JToggleButton.ToggleButtonModel getAddDesktopShortcutModel() {
        return addDesktopShortcut;
    }
    JToggleButton.ToggleButtonModel addStartMenuShortcut;
    public JToggleButton.ToggleButtonModel getAddStartMenuShortcutModel() {
        return addStartMenuShortcut;
    }
    JToggleButton.ToggleButtonModel disableProxy;
    public JToggleButton.ToggleButtonModel getDisableProxyModel() {
        return disableProxy;
    }

    String wsIconPath;
    String splashImagePath;
    String nativeIconPath;
    public String getWSIconPath() {
        return wsIconPath;
    }
    public void setWSIconPath(String path) {
        this.wsIconPath = path;
    }
    public String getSplashImagePath() {
        return splashImagePath;
    }
    public void setSplashImagePath(String path) {
        this.splashImagePath = path;
    }
    public String getNativeIconPath() {
        return nativeIconPath;
    }
    public void setNativeIconPath(String path) {
        this.nativeIconPath = path;
    }
    
    // Deployment - Signing
    public enum SigningType {
        NOSIGN("notsigned"), // NOI18N
        SELF("self"), // NOI18N
        KEY("key"); // NOI18N
        private final String propertyValue;
        SigningType(String propertyValue) {
            this.propertyValue = propertyValue;
        }
        public String getString() {
            return propertyValue;
        }
    }
    boolean signingEnabled;
    boolean signingBlob;
    SigningType signingType;
    String signingKeyStore;
    String signingKeyAlias;
    boolean permissionsElevated;
    char [] signingKeyStorePassword;
    char [] signingKeyPassword;

    public boolean getSigningEnabled() {
        return signingEnabled;
    }
    public void setSigningEnabled(boolean enabled) {
        this.signingEnabled = enabled;
    }
    public boolean getBLOBSigningEnabled() {
        return signingBlob;
    }
    public void setBLOBSigningEnabled(boolean enabled) {
        this.signingBlob = enabled;
    }
    public boolean getPermissionsElevated() {
        return permissionsElevated;
    }
    public void setPermissionsElevated(boolean enabled) {
        this.permissionsElevated = enabled;
    }
    public SigningType getSigningType() {
        return signingType;
    }
    public void setSigningType(SigningType type) {
        this.signingType = type;
    }
    public String getSigningKeyStore() {
        return signingKeyStore;
    }
    public String getSigningKeyAlias() {
        return signingKeyAlias;
    }
    public char[] getSigningKeyStorePassword() {
        return signingKeyStorePassword;
    }
    public char[] getSigningKeyPassword() {
        return signingKeyPassword;
    }
    public void setSigningKeyAlias(String signingKeyAlias) {
        this.signingKeyAlias = signingKeyAlias;
    }
    public void setSigningKeyPassword(char[] signingKeyPassword) {
        this.signingKeyPassword = signingKeyPassword;
    }
    public void setSigningKeyStore(String signingKeyStore) {
        this.signingKeyStore = signingKeyStore;
    }
    public void setSigningKeyStorePassword(char[] signingKeyStorePassword) {
        this.signingKeyStorePassword = signingKeyStorePassword;
    }
    
    // Deployment - Native Packaging (JDK 7u6+)
    public enum BundlingType {
        NONE("none", OS.ALL, "None"), // NOI18N
        ALL("all", OS.ALL, "All Artifacts"), // NOI18N
        IMAGE("image", OS.ALL, "Image Only"), // NOI18N
        INSTALLER("installer", OS.ALL, "All Installers"), // NOI18N
        DEB("deb", OS.LINUX, "DEB Package"), // NOI18N
        RPM("rpm", OS.LINUX, "RPM Package"), // NOI18N
        DMG("dmg", OS.MAC, "DMG Image"), // NOI18N
        EXE("exe", OS.WIN, "EXE Installer"), // NOI18N
        MSI("msi", OS.WIN, "MSI Installer"); // NOI18N
        private final String propertyValue;
        private final String description;
        private final OS extent;
        public enum OS {ALL, WIN, MAC, LINUX, NONE}
        BundlingType(String propertyValue, OS os, String desc) {
            this.propertyValue = propertyValue;
            this.extent = os;
            this.description = desc;
        }
        public String getValue() {
            return propertyValue;
        }
        public OS getExtent() {
            return extent;
        }
        @Override
        public String toString() {
            return description;
        }
    }

    boolean nativeBundlingEnabled;
    public boolean getNativeBundlingEnabled() {
        return nativeBundlingEnabled;
    }
    public void setNativeBundlingEnabled(boolean enabled) {
        this.nativeBundlingEnabled = enabled;
    }
    
    // in SE project - keep jfxrt.jar on classpath
    boolean keepJFXRTonCP;
    public boolean getKeepJFXRTonCP() {
        return keepJFXRTonCP;
    }
    public void setKeepJFXRTonCP(boolean enabled) {
        this.keepJFXRTonCP = enabled;
    }

    // Deployment - Libraries Download Mode
    List<? extends File> runtimeCP;
    List<? extends File> lazyJars;
    boolean lazyJarsChanged;
    public List<? extends File> getRuntimeCP() {
        return runtimeCP;
    }
    public List<? extends File> getLazyJars() {
        return lazyJars;
    }
    public void setLazyJars(List<? extends File> newLazyJars) {
        this.lazyJars = newLazyJars;
    }
    public boolean getLazyJarsChanged() {
        return lazyJarsChanged;
    }
    public void setLazyJarsChanged(boolean changed) {
        this.lazyJarsChanged = changed;
    }
    
    // Deployment - JavaScript Callbacks
    Map<String,String> jsCallbacks;
    boolean jsCallbacksChanged;
    public Map<String,String> getJSCallbacks() {
        return jsCallbacks;
    }
    public void setJSCallbacks(Map<String,String> newCallbacks) {
        jsCallbacks = newCallbacks;
    }
    public boolean getJSCallbacksChanged() {
        return jsCallbacksChanged;
    }
    public void setJSCallbacksChanged(boolean changed) {
        jsCallbacksChanged = changed;
    }
    
    // Deployment - requested RT
    String requestedRT;
    public String getRequestedRT() {
        return requestedRT;
    }
    public void setRequestedRT(String rt) {
        this.requestedRT = rt;
    }
    
    // Application
    String implVersion;
    public String getImplementationVersion() {
        return implVersion;
    }
    public void setImplementationVersion(String implVer) {
        implVersion = implVer;
    }
        
    // Project related references
    private J2SEPropertyEvaluator j2sePropEval;
    private PropertyEvaluator evaluator;
    private Project project;

    public Project getProject() {
        return project;
    }
    public PropertyEvaluator getEvaluator() {
        return evaluator;
    }
    
    /** Keeps singleton instance of JFXProjectProperties for any fx project for which property customizer is opened at once */
    private static Map<String, JFXProjectProperties> propInstance = new HashMap<String, JFXProjectProperties>();

    /** Keeps set of category markers used to identify validity of JFXProjectProperties instance */
    private Set<String> instanceMarkers = new TreeSet<String>();
    
    public void markInstance(@NonNull String marker) {
        instanceMarkers.add(marker);
    }
    
    public boolean isInstanceMarked(@NonNull String marker) {
        return instanceMarkers.contains(marker);
    }
    
    /** Factory method */
    public static JFXProjectProperties getInstance(Lookup context) {
        Project proj = context.lookup(Project.class);
        String projDir = proj.getProjectDirectory().getPath();
        JFXProjectProperties prop = propInstance.get(projDir);
        if(prop == null) {
            prop = new JFXProjectProperties(context);
            propInstance.put(projDir, prop);
        }
        return prop;
    }

    /** Factory method 
     * This is to prevent reuse of the same instance after the properties dialog
     * has been cancelled. Called by each FX category provider at the time
     * when properties dialog is opened, it checks/stores category-specific marker strings. 
     * Previous existence of marker string indicates that properties dialog had been opened
     * before and ended by Cancel, otherwise this instance would not exist (OK would
     * cause properties to be saved and the instance deleted by a call to JFXProjectProperties.cleanup()).
     * (Note that this is a workaround to avoid adding listener to properties dialog close event.)
     * 
     * @param category marker string to indicate which category provider is calling this
     * @return instance of JFXProjectProperties shared among category panels in the current Project Properties dialog only
     * 
     * @deprecated handle cleanup using ProjectCustomizer.Category.setCloseListener instead
     */
    @Deprecated
    public static JFXProjectProperties getInstancePerSession(Lookup context, String category) {
        Project proj = context.lookup(Project.class);
        String projDir = proj.getProjectDirectory().getPath();
        JFXProjectProperties prop = propInstance.get(projDir);
        if(prop != null) {
            if(prop.isInstanceMarked(category)) {
                // category marked before - create new instance to avoid reuse after Cancel
                prop = null;
            } else {
                prop.markInstance(category);
            }
        }
        if(prop == null) {
            prop = new JFXProjectProperties(context);
            propInstance.put(projDir, prop);
            prop.markInstance(category);
        }
        return prop;
    }
    
    /** Getter method */
    public static JFXProjectProperties getInstanceIfExists(Project proj) {
        assert proj != null;
        String projDir = proj.getProjectDirectory().getPath();
        JFXProjectProperties prop = propInstance.get(projDir);
        if(prop != null) {
            return prop;
        }
        return null;
    }

    /** Getter method */
    public static JFXProjectProperties getInstanceIfExists(Lookup context) {
        Project proj = context.lookup(Project.class);
        return getInstanceIfExists(proj);
    }

    public static void cleanup(Lookup context) {
        Project proj = context.lookup(Project.class);
        String projDir = proj.getProjectDirectory().getPath();
        propInstance.remove(projDir);
    }

    /** Keeps singleton instance of a set of preloader artifact dependencies for any fx project */
    private static Map<String, Set<PreloaderArtifact>> prelArtifacts = new HashMap<String, Set<PreloaderArtifact>>();
    
    /** Factory method */
    private static Set<PreloaderArtifact> getPreloaderArtifacts(@NonNull Project proj) {
        String projDir = proj.getProjectDirectory().getPath();
        Set<PreloaderArtifact> prels = prelArtifacts.get(projDir);
        if(prels == null) {
            prels = new HashSet<PreloaderArtifact>();
            prelArtifacts.put(projDir, prels);
        }
        return prels;
    }
    
    public String getFXRunTimeJar() {
        assert evaluator != null;
        String active = evaluator.getProperty(PLATFORM_ACTIVE);
        JavaPlatform platform = JavaFXPlatformUtils.findJavaPlatform(active);
        if(platform != null) {
            return JavaFXPlatformUtils.getJavaFXRuntimeJar(platform);
        }
        return null;
    }
    
    /** Creates a new instance of JFXProjectProperties */
    private JFXProjectProperties(Lookup context) {
        
        //defaultInstance = provider.getJFXProjectProperties();
        project = context.lookup(Project.class);
        
        if (project != null) {
            j2sePropEval = project.getLookup().lookup(J2SEPropertyEvaluator.class);
            evaluator = j2sePropEval.evaluator();
            
            // Packaging
            binaryEncodeCSS = fxPropGroup.createToggleButtonModel(evaluator, JAVAFX_BINARY_ENCODE_CSS); // set true by default in JFXProjectGenerator

            // Deployment
            allowOfflineModel = fxPropGroup.createToggleButtonModel(evaluator, ALLOW_OFFLINE); // set true by default in JFXProjectGenerator            
            backgroundUpdateCheck = fxPropGroup.createToggleButtonModel(evaluator, UPDATE_MODE_BACKGROUND); // set true by default in JFXProjectGenerator
            installPermanently = fxPropGroup.createToggleButtonModel(evaluator, INSTALL_PERMANENTLY);
            addDesktopShortcut = fxPropGroup.createToggleButtonModel(evaluator, ADD_DESKTOP_SHORTCUT);
            addStartMenuShortcut = fxPropGroup.createToggleButtonModel(evaluator, ADD_STARTMENU_SHORTCUT);
            disableProxy = fxPropGroup.createToggleButtonModel(evaluator, DISABLE_PROXY);
            
            // CustomizerRun
            CONFIGS = new JFXConfigs();
            CONFIGS.read();
            initPreloaderArtifacts(project, CONFIGS);
            CONFIGS.setActive(evaluator.getProperty(ProjectProperties.PROP_PROJECT_CONFIGURATION_CONFIG));
            preloaderClassModel = new PreloaderClassComboBoxModel();

            initVersion(evaluator);
            initIcons(evaluator);
            initSigning(evaluator);
            initNativeBundling(evaluator);
            initResources(evaluator, project, CONFIGS);
            initJSCallbacks(evaluator);
            initRest(evaluator);
        }
    }
    
    public static boolean isTrue(final String value) {
        return value != null &&
                (value.equalsIgnoreCase("true") ||  //NOI18N
                 value.equalsIgnoreCase("yes") ||   //NOI18N
                 value.equalsIgnoreCase("on"));     //NOI18N
    }

    public static boolean isNonEmpty(String s) {
        return s != null && !s.isEmpty();
    }
            
    public static boolean isEqual(final String s1, final String s2) {
        return (s1 == null && s2 == null) ||
                (s1 != null && s2 != null && s1.equals(s2));
    }                                   

    public static boolean isEqualIgnoreCase(final String s1, final String s2) {
        return (s1 == null && s2 == null) ||
                (s1 != null && s2 != null && s1.equalsIgnoreCase(s2));
    }                                   

    public static boolean isEqualText(final String s1, final String s2) {
        return ((s1 == null || s1.isEmpty()) && (s2 == null || s2.isEmpty())) ||
                (s1 != null && s2 != null && s1.equals(s2));
    }                                   
    
    /**
     * Used to display named and unnamed parameters in table. The point
     * here is to keep consistency by forbidding invalid parameters, i.e.,
     * named parameters with value but without name.
     */
    public static class PropertiesTableModel extends AbstractTableModel {
        
        private List<Map<String,String>> properties;
        private List<Map<String,String>> defaultProperties;
        private String propSuffixes[];
        private String columnNames[];
        
        public PropertiesTableModel(List<Map<String,String>> props, List<Map<String,String>> defaultProps, String sfxs[], String clmns[]) {
            if (sfxs.length < clmns.length) {
                throw new IllegalArgumentException();
            }
            properties = props;
            defaultProperties = defaultProps;
            propSuffixes = sfxs;
            columnNames = clmns;
        }
        
        public boolean isValid() {
            assert properties != null;
            for(Map<String,String> map : properties) {
                String left = map.get(propSuffixes[0]);
                if(left == null || left.trim().isEmpty()) {
                    for(int c=1; c<columnNames.length; c++) {
                        String right = map.get(propSuffixes[c]);
                        if(right != null && !right.isEmpty()) {
                            return false;
                        }
                    }
                }
            }
            return true;
        }
        
        public boolean hasDefaultProperties() {
            return defaultProperties != null;
        }
        
        public boolean isRowEmpty(int index) {
            if(!properties.isEmpty() && index < properties.size()) {
                Map<String,String> last = properties.get(index);
                for(int c=0; c<columnNames.length; c++) {
                    String value = last.get(propSuffixes[c]);
                    if(value != null && !value.isEmpty()) {
                        return false;
                    }
                }
                return true;
            }
            return false;
        }

        public boolean isLastRowEmpty() {
            return isRowEmpty(properties.size()-1);
        }
        
        @Override
        public int getRowCount() {
            return properties.size();
        }

        @Override
        public int getColumnCount() {
            return columnNames.length;
        }

        @Override
        public String getColumnName(int column) {
            return columnNames[column];
        }
        
        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            if(columnIndex>0) {
                String left = properties.get(rowIndex).get(propSuffixes[columnIndex-1]);
                if(left == null || left.isEmpty()) {
                    return false;
                }
            }
            return true;
        }
        
        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            properties.get(rowIndex).put(propSuffixes[columnIndex], (String) aValue);
            fireTableCellUpdated(rowIndex, columnIndex);
        }
        
        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            return properties.get(rowIndex).get(propSuffixes[columnIndex]);
        }
        
        /**
         * restore defaults if defaultProperties exist, otherwise clean
         */
        public void reset() {
            if(defaultProperties != null) {
                properties.clear();
                properties.addAll(defaultProperties);
            } else {
                properties.clear();
            }
            fireTableDataChanged();
        }
        
        /**
         * Indicates whether it makes sense to enable the Default/Clean
         * button, i.e., whether current table contents differ from the default
         * @return true is a call to reset() would modify data
         */
        public boolean isResettable() {
            if(hasDefaultProperties()) {
                return !areEqual(properties, defaultProperties);
            }
            return !properties.isEmpty();
        }
        
        private boolean areEqual(List<Map<String,String>> list1, List<Map<String,String>> list2) {
            String s1 = getAsString(list1);
            String s2 = getAsString(list2);
            if(isEqualText(s1, s2)) {
                return true;
            }
            return false;
        }
        
        private String getAsString(List<Map<String,String>> list) {
            if(list != null) {
                List<String> l = new LinkedList<String>();
                for(Map<String, String> entry : list) {
                    StringBuilder sb = new StringBuilder();
                    for(int i = 0; i < columnNames.length; i++) {
                        sb.append(propSuffixes[i]);
                        sb.append(entry.get(propSuffixes[i]));
                    }
                    l.add(sb.toString());
                }
                Collections.sort(l);
                return l.toString();
            }
            return null;
        }
        
        public void addRow() {
            Map<String,String> emptyMap = new HashMap<String,String>();
            for (String  suffix : propSuffixes) {
                emptyMap.put(suffix, "");
            }
            properties.add(emptyMap);
            fireTableDataChanged();
        }
        
        public void removeRow(int index) {
            properties.remove(index);
            fireTableDataChanged();
        }
        
        private int getEmptyRow() {
            for(int i = 0; i < properties.size(); i++) {
                if(isRowEmpty(i)) {
                    return i;
                }
            }
            return -1;
        }
        
        public void removeEmptyRows() {
            boolean removed = false;
            while(true) {
                int i = getEmptyRow();
                if(i == -1) {
                    if(removed) {
                        fireTableDataChanged();
                    }
                    return;
                }
                removeRow(i);
                removed = true;
            }
        }

    }

    /**
     * May not be necessary but improves user experience - updates OK button state
     * immediately while editing text in table, i.e., not only after cell editing
     * has finished.
     */
    public static class PropertyCellEditor extends DefaultCellEditor implements CellEditorListener {

        private DocumentListener listener = null;
        private Document document = null;

        public PropertyCellEditor() {
            super(new JTextField());
        }

        public void registerCellEditorListener() {
            addCellEditorListener(this);
        }
        
        public void unregisterCellEditorListener() {
            removeCellEditorListener(this);
        }
        
        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            if(document != null) {
                document.removeDocumentListener(listener);
            }
            JTextField editor = (JTextField) super.getTableCellEditorComponent(table, value, isSelected, row, column);
            document = editor.getDocument();
            listener = new CellEditorDocumentListener(table.getModel(), row, column);
            document.addDocumentListener(listener);
            return editor;
        }

        @Override
        public void editingStopped(ChangeEvent e) {
            removeDocumentListenerReference();
        }

        @Override
        public void editingCanceled(ChangeEvent e) {
            removeDocumentListenerReference();
        }

        private void removeDocumentListenerReference() {
            if(document != null) {
                document.removeDocumentListener(listener);
                document = null;
            }
            listener = null;
        }

        private class CellEditorDocumentListener implements DocumentListener {
            private TableModel model;
            private int row;
            private int column;

            private CellEditorDocumentListener(TableModel model, int row, int column) {
                this.model = model;
                this.row = row;
                this.column = column;
            }
            @Override
            public void insertUpdate(DocumentEvent e) {
                update(e);
            }
            @Override
            public void removeUpdate(DocumentEvent e) {
                update(e);
            }
            @Override
            public void changedUpdate(DocumentEvent e) {
                update(e);
            }

            private void update(DocumentEvent e) {
                Document d = e.getDocument();
                try {
                    model.setValueAt(d.getText(0, d.getLength()), row, column);
                } catch (BadLocationException ex) {
                    // can be ignored
                }
            }
        }
    }

    /**
     * Content in invalid cells is rendered in emphasized color.
     */
    public static class PropertyCellRenderer extends DefaultTableCellRenderer {
        @Override
        public Component getTableCellRendererComponent(JTable table, Object o, boolean isSelected, boolean hasFocus, int row, int column) {
            Component cell = super.getTableCellRendererComponent(table, o, isSelected, hasFocus, row, column);
            if(!table.getModel().isCellEditable(row, column)) {
                cell.setForeground(INVALID_CELL_CONTENT_COLOR);
            } else {
                cell.setForeground(UIManager.getColor("textText")); //NOI18N
            }
            return cell;
        }
    }
    
    
    private FileObject getSrcRoot(@NonNull Project project)
    {
        FileObject srcRoot = null;
        for (SourceGroup sg : ProjectUtils.getSources(project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA)) {
            if (!isTest(sg.getRootFolder(),project)) {
                srcRoot = sg.getRootFolder();
                break;
            }
        }
        return srcRoot;
    }

    private void initPreloaderArtifacts(@NonNull Project project, @NonNull JFXConfigs configs) {
        Set<PreloaderArtifact> prels = getPreloaderArtifacts(project);
        prels.clear();
        try {
            prels.addAll(getPreloaderArtifactsFromConfigs(configs));
        } catch (IOException ex) {
            // can be ignored
        }
    }
    
    public boolean hasPreloaderInAnyConfig() {
        return hasPreloaderInAnyConfig(CONFIGS);
    }
    
    private boolean hasPreloaderInAnyConfig(@NonNull JFXConfigs configs) {
        if(configs != null) {
            for(String config : configs.getConfigNames()) {
                if(isTrue( configs.getProperty(config, PRELOADER_ENABLED))) {
                    return true;
                }
            }
        }
        return false;
    }
    
    private PreloaderArtifact getPreloaderArtifactFromConfig(@NonNull JFXConfigs configs, @NonNull String config, boolean transparent) throws IOException {       
        // check records on any type of preloader from config
        if(configs.hasConfig(config)) {
            
            PreloaderArtifact preloader = null;
            if(!isTrue( transparent ? configs.getPropertyTransparent(config, PRELOADER_ENABLED) : configs.getProperty(config, PRELOADER_ENABLED))) {
                return null;
            }
            String prelTypeString = transparent ? configs.getPropertyTransparent(config, PRELOADER_TYPE) : configs.getProperty(config, PRELOADER_TYPE);
            
            String prelProjDir = transparent ? configs.getPropertyTransparent(config, PRELOADER_PROJECT) : configs.getProperty(config, PRELOADER_PROJECT);
            if (prelProjDir != null && isEqualIgnoreCase(prelTypeString, PreloaderSourceType.PROJECT.getString())) {
                FileObject thisProjDir = project.getProjectDirectory();
                FileObject fo = JFXProjectUtils.getFileObject(thisProjDir, prelProjDir);
                File prelProjDirF = (fo == null) ? null : FileUtil.toFile(fo);                
                if( isTrue(transparent ? configs.getPropertyTransparent(config, PRELOADER_ENABLED) : configs.getProperty(config, PRELOADER_ENABLED)) && prelProjDirF != null && prelProjDirF.exists() ) {
                    FileObject srcRoot = getSrcRoot(getProject());
                    if(srcRoot != null) {
                        prelProjDirF = FileUtil.normalizeFile(prelProjDirF);
                        FileObject prelProjFO = FileUtil.toFileObject(prelProjDirF);
                        final Project proj = ProjectManager.getDefault().findProject(prelProjFO);

                        AntArtifact[] artifacts = proj != null ? AntArtifactQuery.findArtifactsByType(proj, JavaProjectConstants.ARTIFACT_TYPE_JAR) : new AntArtifact[0];
                        List<URI> allURI = new ArrayList<URI>();
                        for(AntArtifact artifact : artifacts) {
                            allURI.addAll(Arrays.asList(artifact.getArtifactLocations()));
                        }
                        if(!allURI.isEmpty()) {
                            URI[] arrayURI = allURI.toArray(new URI[0]);
                            preloader = new PreloaderProjectArtifact(artifacts, arrayURI, srcRoot, ClassPath.COMPILE, prelProjDirF.getAbsolutePath());
                        }
                    }
                }
            }
            if(preloader == null) {
                String prelJar = transparent ? configs.getPropertyTransparent(config, PRELOADER_JAR_PATH) : configs.getProperty(config, PRELOADER_JAR_PATH);
                if(prelJar != null && isEqualIgnoreCase(prelTypeString, PreloaderSourceType.JAR.getString())) {
                    FileObject thisProjDir = project.getProjectDirectory();
                    FileObject fo = JFXProjectUtils.getFileObject(thisProjDir, prelJar);
                    File prelJarF = (fo == null) ? null : FileUtil.toFile(fo);                
                    if( prelJarF != null && prelJarF.exists() ) {
                        FileObject srcRoot = getSrcRoot(getProject());
                        if(srcRoot != null) {
                            URL[] urls = new URL[1];
                            urls[0] = FileUtil.urlForArchiveOrDir(prelJarF);
                            FileObject[] fos = new FileObject[1];
                            fos[0] = FileUtil.toFileObject(prelJarF);
                            preloader = new PreloaderJarArtifact(urls, fos, srcRoot, ClassPath.COMPILE, urls[0].toString());
                        }
                    }
                }
            }
            return preloader;
        }
        return null;
    }
    
    private Set<PreloaderArtifact> getPreloaderArtifactsFromConfigs(@NonNull JFXConfigs configs) throws IOException {       
        Set<PreloaderArtifact> preloaderArtifacts = new HashSet<PreloaderArtifact>();
        // check records on all preloaders from all configurations
        for(String config : configs.getConfigNames()) {
            PreloaderArtifact preloader = getPreloaderArtifactFromConfig(configs, config, false);
            if(preloader != null) {
                preloaderArtifacts.add(preloader);
            }
        }
        return preloaderArtifacts;
    }

    public void updatePreloaderDependencies() {
        try {
            updatePreloaderDependencies(CONFIGS);
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
    }
    
    private void updatePreloaderDependencies(@NonNull final JFXConfigs configs) throws IOException {
        // depeding on the currently (de)selected preloaders update project dependencies,
        // i.e., remove disabled/deleted preloader project dependencies and add enabled/added preloader project dependencies
        Set<PreloaderArtifact> preloaderArtifacts = getPreloaderArtifacts(getProject());
        for(PreloaderArtifact artifact : preloaderArtifacts) {
            artifact.setValid(false);
        }
        final PreloaderArtifact preloaderActive = getPreloaderArtifactFromConfig(configs, configs.getActive(), true);
        // collect all dependencies from any configuration
        for(final String config : configs.getConfigNames()) {
            final PreloaderArtifact preloader = getPreloaderArtifactFromConfig(configs, config, false);
            if(preloader != null) {
                boolean updated = false;
                for(PreloaderArtifact a : preloaderArtifacts) {
                    if(a.equals(preloader)) {
                        a.setValid(true);
                        updated = true;
                    }
                }
                if(!updated) {
                    preloader.setValid(true);
                    preloaderArtifacts.add(preloader);
                }
            }
        }
        // remove all dependencies not-specified in active configuration (and add the active one)
        Set<PreloaderArtifact> toRemove = new HashSet<PreloaderArtifact>();
        for(final PreloaderArtifact artifact : preloaderArtifacts) {
            if(preloaderActive == null || !preloaderActive.equals(artifact)) {
                toRemove.add(artifact);
            }
        }
        if(preloaderActive != null || !toRemove.isEmpty()) {
            final Set<PreloaderArtifact> toRemoveFinal = Collections.unmodifiableSet(toRemove);
            ProjectManager.mutex().postWriteRequest(new Runnable() {
                @Override
                public void run() {
                    if(preloaderActive != null) {
                        try {
                            preloaderActive.addDependency();
                        } catch(IOException e) {
                            LOG.log(Level.SEVERE, "Preloader dependency addition failed."); // NOI18N
                        }
                    }
                    try {
                        for(final PreloaderArtifact artifact : toRemoveFinal) {
                            artifact.removeDependency();
                        }
                    } catch(IOException e) {
                        LOG.log(Level.SEVERE, "Preloader dependency removal failed."); // NOI18N
                    }
                }
            });
        }
        // remove from preloaderArtifacts those not more present in any config
        toRemove.clear();
        for(final PreloaderArtifact artifact : preloaderArtifacts) {
            if(!artifact.isValid()) {
                toRemove.add(artifact);
            }
        }
        for(PreloaderArtifact artifact : toRemove) {
            preloaderArtifacts.remove(artifact);
        }
    }
    
    private static boolean isTest(final @NonNull FileObject root, final @NonNull Project project) {
        assert root != null;
        assert project != null;
        final ClassPath cp = ClassPath.getClassPath(root, ClassPath.COMPILE);
        for (ClassPath.Entry entry : cp.entries()) {
            final FileObject[] srcRoots = SourceForBinaryQuery.findSourceRoots(entry.getURL()).getRoots();
            for (FileObject srcRoot : srcRoots) {
                if (project.equals(FileOwnerQuery.getOwner(srcRoot))) {
                    return true;
                }
            }
        }
        return false;
    }

    private void storeRest(@NonNull EditableProperties editableProps, @NonNull EditableProperties privProps) {
        // create extended manifest attribute properties if not existing
        if(!editableProps.containsKey(MANIFEST_CUSTOM_CODEBASE) && !privProps.containsKey(MANIFEST_CUSTOM_CODEBASE)) {
            editableProps.setProperty(MANIFEST_CUSTOM_CODEBASE, "*"); // NOI18N
            editableProps.setComment(MANIFEST_CUSTOM_CODEBASE, new String[]{"# " + NbBundle.getMessage(JFXProjectUtils.class, "COMMENT_manifest_custom_codebase")}, false); // NOI18N
        }
        if(!editableProps.containsKey(MANIFEST_CUSTOM_PERMISSIONS) && !privProps.containsKey(MANIFEST_CUSTOM_PERMISSIONS)) {
            editableProps.setProperty(MANIFEST_CUSTOM_PERMISSIONS, ""); // NOI18N
            editableProps.setComment(MANIFEST_CUSTOM_PERMISSIONS, new String[]{"# " + NbBundle.getMessage(JFXProjectUtils.class, "COMMENT_manifest_custom_permissions")}, false); // NOI18N
        }
        // store implementation version
        setOrRemove(editableProps, IMPLEMENTATION_VERSION, implVersion);
        // store signing info
        editableProps.setProperty(JAVAFX_SIGNING_ENABLED, signingEnabled ? "true" : "false"); //NOI18N
        editableProps.setProperty(JAVAFX_SIGNING_BLOB, signingBlob ? "true" : "false"); //NOI18N
        editableProps.setProperty(JAVAFX_SIGNING_TYPE, signingType.getString());
        setOrRemove(editableProps, JAVAFX_SIGNING_KEY, signingKeyAlias);
        setOrRemove(editableProps, JAVAFX_SIGNING_KEYSTORE, signingKeyStore);
        editableProps.setProperty(PERMISSIONS_ELEVATED, permissionsElevated ? "true" : "false"); //NOI18N
        setOrRemove(privProps, JAVAFX_SIGNING_KEYSTORE_PASSWORD, signingKeyStorePassword);
        setOrRemove(privProps, JAVAFX_SIGNING_KEY_PASSWORD, signingKeyPassword);        
        // store native bundling info
        editableProps.setProperty(NATIVE_BUNDLING_ENABLED, nativeBundlingEnabled ? "true" : "false"); //NOI18N
        // store icons
        setOrRemove(editableProps, ICON_FILE, wsIconPath);
        setOrRemove(editableProps, SPLASH_IMAGE_FILE, splashImagePath);
        setOrRemove(editableProps, NATIVE_ICON_FILE, nativeIconPath);
        // store requested RT
        setOrRemove(editableProps, REQUEST_RT, requestedRT);
        // store resources
        storeResources(editableProps);
        // store JavaScript callbacks
        storeJSCallbacks(editableProps);
    }

    private void setOrRemove(EditableProperties props, String name, char [] value) {
        setOrRemove(props, name, value != null ? new String(value) : null);
    }

    private void setOrRemove(@NonNull EditableProperties props, @NonNull String name, String value) {
        if (value != null) {
            props.setProperty(name, value);
        } else {
            props.remove(name);
        }
    }
        
    public void store() throws IOException {
        String fxEnabled = evaluator.getProperty(JFXProjectProperties.JAVAFX_ENABLED);
        if(isTrue(fxEnabled)) {
            storeFX();
        } else {
            storeSE();
        }
    }
    
    private void storeFX() throws IOException {
        updatePreloaderDependencies(CONFIGS);
        CONFIGS.storeActive();
        final EditableProperties ep = new EditableProperties(true);
        final FileObject projPropsFO = project.getProjectDirectory().getFileObject(AntProjectHelper.PROJECT_PROPERTIES_PATH);
        final EditableProperties pep = new EditableProperties(true);
        final FileObject privPropsFO = project.getProjectDirectory().getFileObject(AntProjectHelper.PRIVATE_PROPERTIES_PATH);        
        try {
            ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Void>() {
                @Override
                public Void run() throws Exception {
                    final InputStream is = projPropsFO.getInputStream();
                    final InputStream pis = privPropsFO.getInputStream();
                    try {
                        ep.load(is);
                    } finally {
                        if (is != null) {
                            is.close();
                        }
                    }
                    try {
                        pep.load(pis);
                    } finally {
                        if (pis != null) {
                            pis.close();
                        }
                    }
                    
                    fxPropGroup.store(ep);
                    storeRest(ep, pep);
                    CONFIGS.store(ep, pep);
                    updatePreloaderComment(ep);
                    //JFXProjectUtils.updateClassPathExtensionProperties(ep);
                    logProps(ep);

                    OutputStream os = null;
                    FileLock lock = null;
                    try {
                        lock = projPropsFO.lock();
                        os = projPropsFO.getOutputStream(lock);
                        ep.store(os);
                    } finally {
                        if (lock != null) {
                            lock.releaseLock();
                        }
                        if (os != null) {
                            os.close();
                        }
                    }
                    try {
                        lock = privPropsFO.lock();
                        os = privPropsFO.getOutputStream(lock);
                        pep.store(os);
                    } finally {
                        if (lock != null) {
                            lock.releaseLock();
                        }
                        if (os != null) {
                            os.close();
                        }
                    }
                    return null;
                }
            });
        } catch (MutexException mux) {
            throw (IOException) mux.getException();
        }
    }

    private void storeSE() throws IOException {
        final EditableProperties ep = new EditableProperties(true);
        final FileObject projPropsFO = project.getProjectDirectory().getFileObject(AntProjectHelper.PROJECT_PROPERTIES_PATH);
        try {
            final InputStream is = projPropsFO.getInputStream();
            ProjectManager.mutex().readAccess(new Mutex.ExceptionAction<Void>() {
                @Override
                public Void run() throws Exception {
                    try {
                        ep.load(is);
                    } finally {
                        if (is != null) {
                            is.close();
                        }
                    }
                    return null;
                }
            });
        } catch (MutexException mux) {
            throw (IOException) mux.getException();
        }
        setOrRemove(ep, JAVASE_KEEP_JFXRT_ON_CLASSPATH, keepJFXRTonCP ? "true" : null); //NOI18N
        //Copylibs excludes for J2SE Project with JFX extension
        String copyLibsExcludes = ep.getProperty(COPYLIBS_EXCLUDES);
        if (keepJFXRTonCP) {
            if (copyLibsExcludes == null || copyLibsExcludes.isEmpty()) {
                copyLibsExcludes = JFX_EXTENSION_CPREF;
            } else if (copyLibsExcludes.indexOf(JFX_EXTENSION_CPREF)<0){
                copyLibsExcludes = copyLibsExcludes + ':' + JFX_EXTENSION_CPREF;
            }
            setOrRemove(ep, COPYLIBS_EXCLUDES, copyLibsExcludes);
        } else {
            if (copyLibsExcludes != null) {
                copyLibsExcludes = JFXProjectUtils.removeFromPath(copyLibsExcludes,JFX_EXTENSION_CPREF);
                if (copyLibsExcludes.isEmpty()) {
                    copyLibsExcludes = null;
                }
            }
            setOrRemove(ep, COPYLIBS_EXCLUDES, copyLibsExcludes);
        }
        //JFXProjectUtils.updateClassPathExtensionProperties(ep);
        try {
            ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Void>() {
                @Override
                public Void run() throws Exception {
                    OutputStream os = null;
                    FileLock lock = null;
                    try {
                        lock = projPropsFO.lock();
                        os = projPropsFO.getOutputStream(lock);
                        ep.store(os);
                    } finally {
                        if (lock != null) {
                            lock.releaseLock();
                        }
                        if (os != null) {
                            os.close();
                        }
                    }
                    return null;
                }
            });
        } catch (MutexException mux) {
            throw (IOException) mux.getException();
        }
    }
    
    private void updatePreloaderComment(EditableProperties ep) {
        if(isTrue(ep.get(JFXProjectProperties.PRELOADER_ENABLED))) {
            ep.setComment(JFXProjectProperties.PRELOADER_ENABLED, new String[]{"# " + NbBundle.getMessage(JFXProjectProperties.class, "COMMENT_use_preloader")}, false); // NOI18N    
        } else {
            ep.setComment(JFXProjectProperties.PRELOADER_ENABLED, new String[]{"# " + NbBundle.getMessage(JFXProjectProperties.class, "COMMENT_dontuse_preloader")}, false); // NOI18N    
        }
    }

    private void initVersion(PropertyEvaluator eval) {
        implVersion = eval.getProperty(IMPLEMENTATION_VERSION);
        if(implVersion == null) {
            implVersion = IMPLEMENTATION_VERSION_DEFAULT;
        }
    }
    
    private void initIcons(PropertyEvaluator eval) {
        wsIconPath = eval.getProperty(ICON_FILE);
        splashImagePath = eval.getProperty(SPLASH_IMAGE_FILE);
        nativeIconPath = eval.getProperty(NATIVE_ICON_FILE);
    }
    
    private void initSigning(PropertyEvaluator eval) {
        String enabled = eval.getProperty(JAVAFX_SIGNING_ENABLED);
        String blob = eval.getProperty(JAVAFX_SIGNING_BLOB);
        String signedProp = eval.getProperty(JAVAFX_SIGNING_TYPE);
        signingEnabled = isTrue(enabled);
        signingBlob = isTrue(blob);
        if(signedProp == null) {
            signingType = SigningType.NOSIGN;
        } else {
            if(signedProp.equalsIgnoreCase(SigningType.SELF.getString())) {
                signingType = SigningType.SELF;
            } else {
                if(signedProp.equalsIgnoreCase(SigningType.KEY.getString())) {
                    signingType = SigningType.KEY;
                } else {
                    signingType = SigningType.NOSIGN;
                }
            }
        }
        signingKeyStore = eval.getProperty(JAVAFX_SIGNING_KEYSTORE);
        //if (signingKeyStore == null) signingKeyStore = "";
        signingKeyAlias = eval.getProperty(JAVAFX_SIGNING_KEY);
        //if (signingKeyAlias == null) signingKeyAlias = "";
        if (eval.getProperty(JAVAFX_SIGNING_KEYSTORE_PASSWORD) != null) {
            signingKeyStorePassword = eval.getProperty(JAVAFX_SIGNING_KEYSTORE_PASSWORD).toCharArray();
        }
        if (eval.getProperty(JAVAFX_SIGNING_KEY_PASSWORD) != null) {
            signingKeyPassword = eval.getProperty(JAVAFX_SIGNING_KEY_PASSWORD).toCharArray();
        }
        permissionsElevated = isTrue(eval.getProperty(PERMISSIONS_ELEVATED));
    }
    
    private void initNativeBundling(PropertyEvaluator eval) {
        String fxEnabled = evaluator.getProperty(JFXProjectProperties.JAVAFX_ENABLED);
        if(isTrue(fxEnabled)) {
            String enabled = eval.getProperty(NATIVE_BUNDLING_ENABLED);
            nativeBundlingEnabled = isTrue(enabled);
        }
    }
    
    private void initRest(PropertyEvaluator eval) {
        requestedRT = eval.getProperty(REQUEST_RT);
        keepJFXRTonCP = isTrue(eval.getProperty(JAVASE_KEEP_JFXRT_ON_CLASSPATH));
    }
    
    private boolean isParentOf(File parent, File child) {
        if(parent == null || child == null) {
            return false;
        }
        if(!parent.exists() || !child.exists()) {
            return false;
        }
        FileObject parentFO = FileUtil.toFileObject(parent);
        FileObject childFO = FileUtil.toFileObject(child);
        return FileUtil.isParentOf(parentFO, childFO);
    }

    private void initResources (final PropertyEvaluator eval, final Project prj, final JFXConfigs configs) {
        final String lz = eval.getProperty(DOWNLOAD_MODE_LAZY_JARS); //old way, when changed rewritten to new
        final String rcp = eval.getProperty(RUN_CP);        
        final String bc = eval.getProperty(BUILD_CLASSES);
        final String plat = eval.getProperty(PLATFORM_ACTIVE);
        JavaPlatform platform = JavaFXPlatformUtils.findJavaPlatform(plat);
        final File prjDir = FileUtil.toFile(prj.getProjectDirectory());
        final File bcDir = bc == null ? null : PropertyUtils.resolveFile(prjDir, bc);
        final List<File> lazyFileList = new ArrayList<File>();
        String[] paths;
        if (lz != null) {
            paths = PropertyUtils.tokenizePath(lz);            
            for (String p : paths) {
                lazyFileList.add(PropertyUtils.resolveFile(prjDir, p));
            }
        }
        paths = rcp != null ? PropertyUtils.tokenizePath(rcp) : new String[0];
        String mainJar = eval.getProperty(DIST_JAR);
        final File mainFile = mainJar != null ? PropertyUtils.resolveFile(prjDir, mainJar) : null;
        List<FileObject> preloaders = new ArrayList<FileObject>();
        try {
            for(PreloaderArtifact pa : getPreloaderArtifactsFromConfigs(configs)) {
                preloaders.addAll(Arrays.asList(pa.getFileObjects()));
            }
        } catch (IOException ex) {
            // no need to react
        }

        Collection<FileObject> platfF = platform != null ? platform.getInstallFolders() : null;
        final List<File> resFileList = new ArrayList<File>(paths.length);
        for (String p : paths) {
            if (p.startsWith("${") && p.endsWith("}")) {    //NOI18N
                continue;
            }
            final File f = PropertyUtils.resolveFile(prjDir, p);
            if (!f.exists()) {
                continue;
            }
            if (mainFile != null && f.equals(mainFile)) {
                continue;
            }
            if(platfF != null) {
                boolean cont = false;
                for(FileObject fo : platfF) {
                    if(isParentOf(FileUtil.toFile(fo), f)) {
                        cont = true;
                    }
                }
                if(cont) {
                    continue;
                }
            }
            boolean isPrel = false;
            for(FileObject prelfo : preloaders) {
                File prelf = FileUtil.toFile(prelfo);
                if(prelf != null && prelf.equals(f)) {
                    isPrel = true;
                    continue;
                }
            }
            if (!isPrel && (bc == null || !bcDir.equals(f)) ) {
                resFileList.add(f);
                if (isTrue(eval.getProperty(String.format(DOWNLOAD_MODE_LAZY_FORMAT, f.getName())))) {
                    lazyFileList.add(f);
                }
            }
        }
        lazyJars = lazyFileList;
        runtimeCP = resFileList;
        lazyJarsChanged = false;
    }
    
    private void storeResources(final EditableProperties props) {
        if (lazyJarsChanged) {
            //Remove old way if exists
            props.remove(DOWNLOAD_MODE_LAZY_JARS);
            final Iterator<Map.Entry<String,String>> it = props.entrySet().iterator();
            while (it.hasNext()) {
                if (it.next().getKey().startsWith(DOWNLOAD_MODE_LAZY_JAR)) {
                    it.remove();
                }
            }
            for (File lazyJar : lazyJars) {
                props.setProperty(String.format(DOWNLOAD_MODE_LAZY_FORMAT, lazyJar.getName()), "true");  //NOI18N
            }
        }
    }

    private void initJSCallbacks (final PropertyEvaluator eval) {
        String platformName = eval.getProperty(PLATFORM_ACTIVE);
        Map<String,List<String>/*|null*/> callbacks = JFXProjectUtils.getJSCallbacks(platformName);
        Map<String,String/*|null*/> result = new LinkedHashMap<String,String/*|null*/>();
        for(Map.Entry<String,List<String>/*|null*/> entry : callbacks.entrySet()) {
            String v = eval.getProperty(JFXProjectProperties.JAVASCRIPT_CALLBACK_PREFIX + entry.getKey());
            if(v != null && !v.isEmpty()) {
                result.put(entry.getKey(), v);
            }
        }
        jsCallbacks = result;
        jsCallbacksChanged = false;
    }
    
    private void storeJSCallbacks(final EditableProperties props) {
        if (jsCallbacksChanged && jsCallbacks != null) {
            for (Map.Entry<String,String> entry : jsCallbacks.entrySet()) {
                if(entry.getValue() != null && !entry.getValue().isEmpty()) {
                    props.setProperty(JAVASCRIPT_CALLBACK_PREFIX + entry.getKey(), entry.getValue());  //NOI18N
                } else {
                    props.remove(JAVASCRIPT_CALLBACK_PREFIX + entry.getKey());
                }
            }
        }
    }

    public class PreloaderClassComboBoxModel extends DefaultComboBoxModel {
        
        private volatile boolean filling = false;
        private ChangeListener changeListener = null;
              
        public PreloaderClassComboBoxModel() {
            fillNoPreloaderAvailable();
        }
        
        public void addChangeListener (ChangeListener l) {
            changeListener = l;
        }

        public void removeChangeListener (ChangeListener l) {
            changeListener = null;
        }

        public final void fillNoPreloaderAvailable() {
            removeAllElements();
            addElement(NbBundle.getMessage(JFXProjectProperties.class, "MSG_ComboNoPreloaderClassAvailable"));  // NOI18N
        }
        
        public void fillFromProject(final Project project, final String select, final JFXConfigs configs, final String activeConfig) {
            final Collection<? extends FileObject> roots = JFXProjectUtils.getClassPathMap(project).keySet();
            RequestProcessor.getDefault().post(new Runnable() {
                @Override
                public void run() {
                    if(!filling) {
                        filling = true;
                        removeAllElements();
                        if(project == null) {
                            addElement(NbBundle.getMessage(JFXProjectProperties.class, "MSG_ComboNoPreloaderClassAvailable"));  // NOI18N
                            return;
                        }
                        final Set<String> appClassNames = JFXProjectUtils.getAppClassNames(roots, "javafx.application.Preloader"); //NOI18N
                        if(appClassNames.isEmpty()) {
                            addElement(NbBundle.getMessage(JFXProjectProperties.class, "MSG_ComboNoPreloaderClassAvailable"));  // NOI18N
                        } else {
                            addElements(appClassNames);
                            if(select != null) {
                                setSelectedItem(select);
                            }
                            String verify = (String)getSelectedItem();
                            if(!isEqual(configs.getPropertyTransparent(activeConfig, JFXProjectProperties.PRELOADER_CLASS), verify)) {
                                configs.setPropertyTransparent(activeConfig, JFXProjectProperties.PRELOADER_CLASS, verify);
                            }
                        }
                        if (changeListener != null) {
                            changeListener.stateChanged (appClassNames.isEmpty() ? null : new ChangeEvent (this));
                        }
                        filling = false;
                    }
                }
            });            
        }

        public void fillFromJAR(final FileObject jarFile, final JFXProjectProperties fxProps, final String select, final JFXConfigs configs, final String activeConfig) {
            RequestProcessor.getDefault().post(new Runnable() {
                @Override
                public void run() {
                    if(!filling) {
                        filling = true;
                        removeAllElements();
                        if(jarFile == null) {
                            addElement(NbBundle.getMessage(JFXProjectProperties.class, "MSG_ComboNoPreloaderClassAvailable"));  // NOI18N
                            return;
                        }
                        final Set<String> appClassNames = JFXProjectUtils.getAppClassNamesInJar(jarFile, "javafx.application.Preloader", fxProps.getFXRunTimeJar()); //NOI18N    
                        appClassNames.remove("com.javafx.main.Main"); // NOI18N
                        appClassNames.remove("com.javafx.main.NoJavaFXFallback"); // NOI18N
                        if(appClassNames.isEmpty()) {
                            addElement(NbBundle.getMessage(JFXProjectProperties.class, "MSG_ComboNoPreloaderClassAvailable"));  // NOI18N
                        } else {
                            addElements(appClassNames);
                            if(select != null) {
                                setSelectedItem(select);
                            }
                            String verify = (String)getSelectedItem();
                            if(!isEqual(configs.getPropertyTransparent(activeConfig, JFXProjectProperties.PRELOADER_CLASS), verify)) {
                                configs.setPropertyTransparent(activeConfig, JFXProjectProperties.PRELOADER_CLASS, verify);
                            }
                        }
                        if (changeListener != null) {
                            changeListener.stateChanged (appClassNames.isEmpty() ? null : new ChangeEvent (this));
                        }
                        filling = false;
                    }
                }
            });            
        }

        private void addElements(Set<String> elems) {
            for (String elem : elems) {
                addElement(elem);
            }
        }
        
    }
    
    /**
     * Each preloader specified in project configurations needs
     * to be added/removed to/from project dependencies whenever
     * configurations change (see Run category in Project Properties
     * dialog). 
     * List of preoader artifacts is thus needed to keep track which
     * project dependencies are preloader related.
     */
    abstract class PreloaderArtifact {
        
        /**
         * Dependency validity tag
         */
        private boolean valid;
        
        /**
         * Add {@code this} to dependencies of project if it is not there yet
         * @return true if preloader artifact has been added, false if it was already there
         */
        abstract boolean addDependency() throws IOException, UnsupportedOperationException;
        
        /**
         * Remove {@code this} from dependencies of project if it is there
         * @return true if preloader artifact has been removed, false if it was not among project dependencies
         */
        abstract boolean removeDependency() throws IOException, UnsupportedOperationException;
        
        /**
         * Returns array of files represented by this PreloaderArtifact
         * @return array of FileObjects of files represented by this object
         */
        abstract FileObject[] getFileObjects();
        
        /**
         * Set the validity tag for {@code this} artifact
         * @param valid true for dependencies to be kept, false for dependencies to be removed
         */
        void setValid(boolean valid) {
            this.valid = valid;
        }
        
        /**
         * Get the validity tag for {@code this} artifact
         * @return valid true for dependencies to be kept, false for dependencies to be removed
         */
        boolean isValid() {
            return valid;
        }
    }
    
    class PreloaderProjectArtifact extends PreloaderArtifact {

        private final String ID;
        private final AntArtifact[] artifacts;
        private final URI[] artifactElements;
        private final FileObject projectArtifact;
        private final String classPathType;
                
        PreloaderProjectArtifact(final @NonNull AntArtifact[] artifacts, final @NonNull URI[] artifactElements,
            final @NonNull FileObject projectArtifact, final @NonNull String classPathType, final @NonNull String ID) {
            this.artifacts = artifacts;
            this.artifactElements = artifactElements;
            this.projectArtifact = projectArtifact;
            this.classPathType = classPathType;
            this.ID = ID;
        }
        
        @Override
        public boolean addDependency() throws IOException, UnsupportedOperationException {
            return ProjectClassPathModifier.addAntArtifacts(artifacts, artifactElements, projectArtifact, classPathType);
        }

        @Override
        public boolean removeDependency()  throws IOException, UnsupportedOperationException {
            return ProjectClassPathModifier.removeAntArtifacts(artifacts, artifactElements, projectArtifact, classPathType);
        }

        @Override
        public boolean equals(Object that){
            if ( this == that ) return true;
            if ( !(that instanceof PreloaderProjectArtifact) ) return false;
            PreloaderProjectArtifact concrete = (PreloaderProjectArtifact)that;
            return ID.equals(concrete.ID);
        }

        @Override
        final FileObject[] getFileObjects() {
            List<FileObject> l = new ArrayList<FileObject>();
            for(AntArtifact a : artifacts) {
                l.addAll(Arrays.asList(a.getArtifactFiles()));
            }
            return l.toArray(new FileObject[l.size()]);
        }
    }

    class PreloaderJarArtifact extends PreloaderArtifact {

        private final String ID;
        private final URL[] classPathRoots;
        private final FileObject[] fileObjects;
        private final FileObject projectArtifact;
        private final String classPathType;
                
        PreloaderJarArtifact(final @NonNull URL[] classPathRoots, final @NonNull FileObject[] fileObjects, final @NonNull FileObject projectArtifact, 
                final @NonNull String classPathType, final @NonNull String ID) {
            this.classPathRoots = classPathRoots;
            this.fileObjects = fileObjects;
            this.projectArtifact = projectArtifact;
            this.classPathType = classPathType;
            this.ID = ID;
        }
        
        @Override
        public boolean addDependency() throws IOException, UnsupportedOperationException {
            return ProjectClassPathModifier.addRoots(classPathRoots, projectArtifact, classPathType);
        }

        @Override
        public boolean removeDependency()  throws IOException, UnsupportedOperationException {
            return ProjectClassPathModifier.removeRoots(classPathRoots, projectArtifact, classPathType);
        }
        
        @Override
        public boolean equals(Object that){
            if ( this == that ) return true;
            if ( !(that instanceof PreloaderJarArtifact) ) return false;
            PreloaderJarArtifact concrete = (PreloaderJarArtifact)that;
            return ID.equals(concrete.ID);
        }

        @Override
        final FileObject[] getFileObjects() {
            return fileObjects;
        }
    }

    /**
     * Project configurations maintenance class
     * 
     * Getter/Setter naming conventions:
     * "Property" in method name -> method deals with single properties in configuration given by parameter config
     * "Default" in method name -> method deals with properties in default configuration
     * "Active" in method name -> method deals with properties in currently chosen configuration
     * "Transparent" in method name -> method deals with property in configuration fiven by parameter config if
     *     exists, or with property in default configuration otherwise. This is to provide simple access to
     *     union of default and non-default properties that are to be presented to users in non-default configurations
     * "Param" in method name -> metod deals with properties representing sets of application parameters
     */
    public class JFXConfigs extends JFXProjectConfigurations {

        // property groups
        private String PRELOADER_GROUP_NAME = "preloader"; // NOI18N
        private List<String> PRELOADER_PROPERTIES = Arrays.asList(new String[] {
            JFXProjectProperties.PRELOADER_ENABLED, JFXProjectProperties.PRELOADER_TYPE, JFXProjectProperties.PRELOADER_PROJECT, 
            JFXProjectProperties.PRELOADER_JAR_PATH, JFXProjectProperties.PRELOADER_JAR_FILENAME, JFXProjectProperties.PRELOADER_CLASS});

        private String BROWSER_GROUP_NAME = "browser"; // NOI18N
        private List<String> BROWSER_PROPERTIES = Arrays.asList(new String[] {
            JFXProjectProperties.RUN_IN_BROWSER, JFXProjectProperties.RUN_IN_BROWSER_PATH, JFXProjectProperties.RUN_IN_BROWSER_ARGUMENTS});
        
        public final List<String> getPreloaderProperties() {
            return Collections.unmodifiableList(PRELOADER_PROPERTIES);
        }
        
        public final List<String> getBrowserProperties() {
            return Collections.unmodifiableList(BROWSER_PROPERTIES);
        }

        JFXConfigs() {
            super(project.getProjectDirectory());
            registerProjectProperties(new String[] {
                ProjectProperties.MAIN_CLASS, MAIN_CLASS, /*APPLICATION_ARGS,*/ RUN_JVM_ARGS, 
                PRELOADER_ENABLED, PRELOADER_TYPE, PRELOADER_PROJECT, PRELOADER_JAR_PATH, PRELOADER_JAR_FILENAME, PRELOADER_CLASS, 
                RUN_WORK_DIR, RUN_APP_WIDTH, RUN_APP_HEIGHT, RUN_IN_HTMLTEMPLATE, RUN_IN_BROWSER, RUN_IN_BROWSER_PATH, RUN_AS});
            registerPrivateProperties(new String[] {
                RUN_WORK_DIR, RUN_IN_HTMLTEMPLATE, RUN_IN_BROWSER, RUN_IN_BROWSER_PATH, RUN_IN_BROWSER_ARGUMENTS, RUN_AS});
            registerStaticProperties(new String[] {
                RUN_AS});
            
            Map<String, String> substituteMissing = new HashMap<String, String>();
            substituteMissing.put(RUN_APP_WIDTH, DEFAULT_APP_WIDTH);
            substituteMissing.put(RUN_APP_HEIGHT, DEFAULT_APP_HEIGHT);
            registerDefaultsIfMissing(substituteMissing);
            
            registerCleanEmptyProjectProperties(new String[] {
                MAIN_CLASS, RUN_JVM_ARGS, 
                PRELOADER_ENABLED, PRELOADER_TYPE, PRELOADER_PROJECT, PRELOADER_JAR_PATH, PRELOADER_JAR_FILENAME, PRELOADER_CLASS, 
                RUN_APP_WIDTH, RUN_APP_HEIGHT});
            registerCleanEmptyPrivateProperties(new String[] {
                RUN_WORK_DIR, RUN_IN_HTMLTEMPLATE, RUN_IN_BROWSER, RUN_IN_BROWSER_PATH});
            
            defineGroup(PRELOADER_GROUP_NAME, getPreloaderProperties());
            defineGroup(BROWSER_GROUP_NAME, getBrowserProperties());
        }
        
    }
    
    static void logProps(EditableProperties ep) {
        LOG.log(Level.INFO, PRELOADER_ENABLED + " = " + (ep.get(PRELOADER_ENABLED)==null ? "null" : ep.get(PRELOADER_ENABLED)));
        LOG.log(Level.INFO, PRELOADER_TYPE + " = " + (ep.get(PRELOADER_TYPE)==null ? "null" : ep.get(PRELOADER_TYPE)));
        LOG.log(Level.INFO, PRELOADER_PROJECT + " = " + (ep.get(PRELOADER_PROJECT)==null ? "null" : ep.get(PRELOADER_PROJECT)));
        LOG.log(Level.INFO, PRELOADER_CLASS + " = " + (ep.get(PRELOADER_CLASS)==null ? "null" : ep.get(PRELOADER_CLASS)));
        LOG.log(Level.INFO, PRELOADER_JAR_FILENAME + " = " + (ep.get(PRELOADER_JAR_FILENAME)==null ? "null" : ep.get(PRELOADER_JAR_FILENAME)));
        LOG.log(Level.INFO, PRELOADER_JAR_PATH + " = " + (ep.get(PRELOADER_JAR_PATH)==null ? "null" : ep.get(PRELOADER_JAR_PATH)));
    }
}
