All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modules.glassfish.common.GlassfishInstance Maven / Gradle / Ivy

/*
 * 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.glassfish.common;

import java.io.*;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComponent;
import org.netbeans.modules.glassfish.tooling.TaskState;
import org.netbeans.modules.glassfish.tooling.data.GlassFishAdminInterface;
import org.netbeans.modules.glassfish.tooling.data.GlassFishServer;
import org.netbeans.modules.glassfish.tooling.data.GlassFishVersion;
import org.netbeans.modules.glassfish.tooling.utils.ServerUtils;
import org.netbeans.api.java.platform.JavaPlatform;
import org.netbeans.api.java.platform.JavaPlatformManager;
import org.netbeans.api.keyring.Keyring;
import org.netbeans.api.server.ServerInstance;
import org.netbeans.modules.glassfish.common.nodes.Hk2InstanceNode;
import org.netbeans.modules.glassfish.common.parser.DomainXMLChangeListener;
import org.netbeans.modules.glassfish.common.ui.GlassFishPropertiesCustomizer;
import org.netbeans.modules.glassfish.common.ui.WarnPanel;
import org.netbeans.modules.glassfish.common.utils.Util;
import org.netbeans.modules.glassfish.spi.*;
import org.netbeans.modules.glassfish.spi.GlassfishModule.ServerState;
import org.netbeans.spi.server.ServerInstanceFactory;
import org.netbeans.spi.server.ServerInstanceImplementation;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.nodes.Node;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
import org.openide.util.lookup.AbstractLookup;
import org.openide.util.lookup.InstanceContent;
import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ProxyLookup;
import org.openide.windows.InputOutput;

/**
 * GlassFish server instance.
 * 

* Represents any GlassFish server registered in NetBeans. *

* @author Peter Williams, Vince Kraemer, Tomas Kraus */ public class GlassfishInstance implements ServerInstanceImplementation, Lookup.Provider, LookupListener, GlassFishServer { //////////////////////////////////////////////////////////////////////////// // Inner classes // //////////////////////////////////////////////////////////////////////////// /** * Properties map used to store GlassFish server properties in GlassFish * server instance. */ public class Props implements Map { private final Map delegate; /** * Constructs a new properties map with the same mappings as the * specified Map. *

* The Props is created with default load factor (0.75) * and an initial capacity sufficient to hold the mappings in the * specified Map. *

* @param map Properties Map whose mappings are to be * placed in this map. * @throws NullPointerException if the specified map is null. */ public Props(Map map) { if (map == null) { throw new NullPointerException("Source Map shall not be null."); } this.delegate = map; } @Override public Collection values() { synchronized(delegate) { return Collections.unmodifiableCollection( delegate.values()); } } @Override public Set keySet() { synchronized(delegate) { return Collections.unmodifiableSet(delegate.keySet()); } } @Override public Set> entrySet() { synchronized(delegate) { return Collections.>unmodifiableSet( delegate.entrySet()); } } @Override public int size() { synchronized(delegate) {return delegate.size();} } @Override public String remove(Object key) { synchronized(delegate) {return delegate.remove(key);} } @Override public void putAll(Map m) { synchronized(delegate) {delegate.putAll(m);} } @Override public String put(String key, String value) { if (GlassfishModule.PASSWORD_ATTR.equals(key)) { String serverName = get(GlassfishModule.DISPLAY_NAME_ATTR); String userName = get(GlassfishModule.USERNAME_ATTR); if (serverName != null && userName != null) { Keyring.save(GlassfishInstance.passwordKey( serverName, userName), value.toCharArray(), "GlassFish administrator user password"); } } synchronized(delegate) {return delegate.put(key, value);} } @Override public boolean isEmpty() { synchronized(delegate) {return delegate.isEmpty();} } @Override public int hashCode() { synchronized(delegate) {return delegate.hashCode();} } @Override public boolean equals(Object o) { if (o == this) return true; if (o instanceof Map) synchronized(delegate) {return delegate.equals(o);} else return false; } @Override public boolean containsValue(Object value) { synchronized(delegate) {return delegate.containsValue(value);} } @Override public boolean containsKey(Object key) { synchronized(delegate) {return delegate.containsKey(key);} } @Override public void clear() { synchronized(delegate) {delegate.clear();} } /** * Returns the property value to which the specified property key * is mapped, or null if this map contains no mapping for * the key. *

* @param key Property key used to search for mapped property value. * @return Property value mapped to specified property key * or null if no such property value exists. */ @Override public String get(Object key) { if (GlassfishModule.PASSWORD_ATTR.equals(key)) { String value; synchronized(delegate) { value = delegate.get(key); } if (value == null) { value = getPasswordFromKeyring( delegate.get(GlassfishModule.DISPLAY_NAME_ATTR), delegate.get(GlassfishModule.USERNAME_ATTR)); synchronized(delegate) { delegate.put((String)key, value); } } return value; } else { synchronized(delegate) {return delegate.get(key);} } } } //////////////////////////////////////////////////////////////////////////// // Class attributes // //////////////////////////////////////////////////////////////////////////// /** Local logger. */ private static final Logger LOGGER = GlassFishLogger.get(GlassfishInstance.class); // Reasonable default values for various server parameters. Note, don't use // these unless the server's actual setting cannot be determined in any way. public static final String DEFAULT_HOST_NAME = "localhost"; // NOI18N public static final String DEFAULT_ADMIN_NAME = "admin"; // NOI18N public static final String DEFAULT_ADMIN_PASSWORD = ""; // NOI18N /** Administrator's password being used in old NetBeans. */ public static final String OLD_DEFAULT_ADMIN_PASSWORD = "adminadmin"; // NOI18N public static final int DEFAULT_HTTP_PORT = 8080; public static final int DEFAULT_HTTPS_PORT = 8181; public static final int DEFAULT_ADMIN_PORT = 4848; public static final int DEFAULT_DEBUG_PORT = 9009; static final int LOWEST_USER_PORT = org.openide.util.Utilities.isWindows() ? 1 : 1025; public static final String DEFAULT_DOMAINS_FOLDER = "domains"; //NOI18N public static final String DEFAULT_DOMAIN_NAME = "domain1"; // NOI18N static final String INSTANCE_FO_ATTR = "InstanceFOPath"; // NOI18N /** GlassFish user account instance key ring name space. */ static final String KEYRING_NAME_SPACE="GlassFish.admin"; /** * GlassFish user account instance key ring field separator. *

* Key ring name is constructed in following form: * {'.'}':' * e.g. "GlassFish.cloud.userAccount.userPassword:someUser". */ static final String KEYRING_NAME_SEPARATOR="."; /** * GlassFish user account instance key ring identifier separator. *

* Key ring name is constructed in following form: * {'.'}':' * e.g. "GlassFish.cloud.userAccount.userPassword:someUser". */ static final String KEYRING_IDENT_SEPARATOR=":"; //////////////////////////////////////////////////////////////////////////// // Static methods // //////////////////////////////////////////////////////////////////////////// /** * Build key ring identifier for password related to given user name. *

* @param serverName Name of server to add into password key. * @param userName User name of account user who's password will be stored. * @return Key ring identifier for password related to given user name */ public static String passwordKey(String serverName, String userName) { StringBuilder pwKey = new StringBuilder( KEYRING_NAME_SPACE.length() + KEYRING_NAME_SEPARATOR.length() + GlassfishModule.PASSWORD_ATTR.length() + KEYRING_IDENT_SEPARATOR.length() + (serverName != null ? serverName.length() : 0) + KEYRING_IDENT_SEPARATOR.length() + (userName != null ? userName.length() : 0)); pwKey.append(KEYRING_NAME_SPACE); pwKey.append(KEYRING_NAME_SEPARATOR); pwKey.append(GlassfishModule.PASSWORD_ATTR); pwKey.append(KEYRING_IDENT_SEPARATOR); pwKey.append(serverName != null ? serverName : ""); pwKey.append(KEYRING_IDENT_SEPARATOR); pwKey.append(userName != null ? userName : ""); return pwKey.toString(); } /** * Retrieve password stored in {@see Keyring}. *

* @param serverName Name of server to add into password key. * @param userName User name of account user who's password will be read. * @return */ public static String getPasswordFromKeyring(final String serverName, final String userName) { char[] passwordChars = Keyring.read( GlassfishInstance.passwordKey(serverName, userName)); String value = passwordChars != null ? new String(passwordChars) : DEFAULT_ADMIN_PASSWORD; return value; } /** * Find all modules that have NetBeans support, add them to * GlassfishInstance local lookup if server supports them. *

* @param instance GlassfishInstance local lookup to be updated. */ static void updateModuleSupport(GlassfishInstance instance) { instance.updateFactories(); instance.lookupResult.addLookupListener(instance); } /** * Mark this GlassFish server URL as under construction. *

* Will do nothing if provided url argument * is null. *

* @param url GlassFish server URL */ private static void tagUnderConstruction(String url) { if (url != null) { GlassfishInstanceProvider.activeRegistrationSet.add(url); } } /** * Remove under construction URL mark from this GlassFish server. *

* Will do nothing if provided url argument * is null. *

* @param url GlassFish server URL */ private static void untagUnderConstruction(String url) { if (url != null) { GlassfishInstanceProvider.activeRegistrationSet.remove(url); } } /** * Creates a GlassfishInstance object for a server installation. This * instance should be added to the the provider registry if the caller wants * it to be persisted for future sessions or searchable. *

* @param displayName Display name for this server instance. * @param installRoot GlassFish installation root directory. * @param glassfishRoot GlassFish server home directory. * @param domainsDir GlassFish server domains directory. * @param domainName GlassFish server registered domain name. * @param httpPort GlassFish server HTTP port for applications. * @param adminPort GlassFish server HTTP port for administration. * @param userName GlassFish server administrator's user name. * @param password GlassFish server administrator's password. * @param url GlassFish server URL (Java EE SPI unique identifier). * @param gip GlassFish instance provider. * @return GlassfishInstance object for this server instance. */ public static GlassfishInstance create(String displayName, String installRoot, String glassfishRoot, String domainsDir, String domainName, int httpPort, int adminPort, String userName, String password, String target, String url, GlassfishInstanceProvider gip) { Map ip = new HashMap<>(); ip.put(GlassfishModule.DISPLAY_NAME_ATTR, displayName); ip.put(GlassfishModule.INSTALL_FOLDER_ATTR, installRoot); ip.put(GlassfishModule.GLASSFISH_FOLDER_ATTR, glassfishRoot); ip.put(GlassfishModule.DOMAINS_FOLDER_ATTR, domainsDir); ip.put(GlassfishModule.DOMAIN_NAME_ATTR, domainName); ip.put(GlassfishModule.HTTPPORT_ATTR, Integer.toString(httpPort)); ip.put(GlassfishModule.ADMINPORT_ATTR, Integer.toString(adminPort)); ip.put(GlassfishModule.TARGET_ATTR, target); ip.put(GlassfishModule.USERNAME_ATTR, userName != null ? userName : DEFAULT_ADMIN_NAME); if (password != null) { ip.put(GlassfishModule.PASSWORD_ATTR, password); } ip.put(GlassfishModule.URL_ATTR, url); // extract the host from the URL String[] bigUrlParts = url.split("]"); if (null != bigUrlParts && bigUrlParts.length > 1) { String[] urlParts = bigUrlParts[1].split(":"); // NOI18N if (null != urlParts && urlParts.length > 2) { ip.put(GlassfishModule.HOSTNAME_ATTR, urlParts[2]); ip.put(GlassfishModule.HTTPHOST_ATTR, urlParts[2]); } } return create(ip, gip, true); } /** * Constructs an instance of GlassFish instance data object and initializes * it. *

* @param ip GlassFish instance properties. * @param gip GlassFish instance provider. * @param updateNow Trigger lookup update. * @return Initialized GlassFish instance data object. */ public static GlassfishInstance create(Map ip, GlassfishInstanceProvider gip, boolean updateNow) { String deployerUri = ip.get(GlassfishModule.URL_ATTR); GlassfishInstance instance = null; GlassFishVersion version = ServerUtils.getServerVersion( ip.get(GlassfishModule.GLASSFISH_FOLDER_ATTR)); try { instance = new GlassfishInstance(ip, version, gip, updateNow); tagUnderConstruction(deployerUri); if (!instance.isPublicAccess()) { instance.ic.add(instance.commonSupport); instance.allowPublicAccess(); } if (updateNow) { updateModuleSupport(instance); } } finally { untagUnderConstruction(deployerUri); } LOGGER.log(Level.INFO, "Created GlassFish Server {0} instance with name {1}", new String[] {version != null ? version.toString() : "null", instance != null ? instance.getName() : "null"}); return instance; } /** * Constructs an instance of GlassFish instance data object and initializes * it. *

* Lookup update will be done by default. *

* @param ip GlassFish instance properties. * @param gip GlassFish instance provider. * @param updateNow Trigger lookup update. * @return Initialized GlassFish instance data object. */ public static GlassfishInstance create(Map ip, GlassfishInstanceProvider gip) { return create(ip, gip, true); } /** * Add new String storedValue into Map when storedValue * with specified key does not exist. *

* @param map Map to be checked and updated. * @param key Key used to search for already existing storedValue. * @param value Value to be added when nothing is found. * @return Value stored in Map or value argument * when no value was stored int the Map */ private static String updateString(Map map, String key, String value) { String result = map.get(key); if(result == null) { map.put(key, value); result = value; } return result; } /** * Add new Integer storedValue into Map when storedValue * with specified key does not exist. *

* @param map Map to be checked and updated. * @param key Key used to search for already existing storedValue. * @param value Value to be added when nothing is found. * @return Value stored in Map or value argument * when no value was stored int the Map */ private static int updateInt(Map map, String key, int value) { int result; String storedValue = map.get(key); try { // Throws NumberFormatException also when storedValue is null. result = Integer.parseInt(storedValue); } catch(NumberFormatException ex) { map.put(key, Integer.toString(value)); result = value; } return result; } /** * Check if given GlassFish instance properties keys should be filtered * when persisting GlassFish instance. *

* @param key GlassFish instance properties key to be checked. * @return Value of true when property with given key shall not * be persisted or false otherwise. */ private static boolean filterKey(String key) { return INSTANCE_FO_ATTR.equals(key); } /** * Fix attributes being imported from old NetBeans. *

* Password for local server is changed from "adminadmin" * to "". * Fixed attributes are marked with new property to avoid multiple fixes * in the future. *

* Argument ip shall not be null. *

* @param ip Instance properties Map. * @param fo Instance file object. */ private static void fixImportedAttributes(Map ip, FileObject fo) { if (!ip.containsKey(GlassfishModule.NB73_IMPORT_FIXED)) { String password = ip.get(GlassfishModule.PASSWORD_ATTR); if (password != null) { boolean local = ip.get(GlassfishModule.DOMAINS_FOLDER_ATTR) != null; if (local && GlassfishInstance.OLD_DEFAULT_ADMIN_PASSWORD .equals(password)) { if (GlassfishInstance.DEFAULT_ADMIN_PASSWORD == null || GlassfishInstance .DEFAULT_ADMIN_PASSWORD.length() == 0) { ip.remove(GlassfishModule.PASSWORD_ATTR); } else { ip.put(GlassfishModule.PASSWORD_ATTR, GlassfishInstance.DEFAULT_ADMIN_PASSWORD); } org.netbeans.modules.glassfish.common.utils.ServerUtils .setStringAttribute(fo, GlassfishModule.PASSWORD_ATTR, GlassfishInstance.DEFAULT_ADMIN_PASSWORD); } } ip.put(GlassfishModule.NB73_IMPORT_FIXED, Boolean.toString(true)); } } // Password from keyring (GlassfishModule.PASSWORD_ATTR) is read on demand // using code in GlassfishInstance.Props class. /** * Read GlassFish server instance data from persistent storage. *

* @param instanceFO Persistent storage file. * @param uriFragment GlassFish server URI fragment. * @return GlassFish server instance reconstructed from persistent storage. * @throws IOException */ public static GlassfishInstance readInstanceFromFile( FileObject instanceFO, boolean autoregistered) throws IOException { GlassfishInstance instance = null; String installRoot = org.netbeans.modules.glassfish.common.utils.ServerUtils .getStringAttribute(instanceFO, GlassfishModule.INSTALL_FOLDER_ATTR); String glassfishRoot = org.netbeans.modules.glassfish.common.utils.ServerUtils .getStringAttribute(instanceFO, GlassfishModule.GLASSFISH_FOLDER_ATTR); // Existing installs may lack "installRoot", but glassfishRoot and // installRoot are the same in that case. if(installRoot == null) { installRoot = glassfishRoot; } // TODO: Implement better folders content validation. if(org.netbeans.modules.glassfish.common.utils.ServerUtils .isValidFolder(installRoot) && org.netbeans.modules.glassfish.common.utils.ServerUtils .isValidFolder(glassfishRoot)) { // collect attributes and pass to create() Map ip = new HashMap<>(); Enumeration iter = instanceFO.getAttributes(); while(iter.hasMoreElements()) { String name = iter.nextElement(); String value = org.netbeans.modules.glassfish.common.utils .ServerUtils.getStringAttribute(instanceFO, name); ip.put(name, value); } ip.put(INSTANCE_FO_ATTR, instanceFO.getName()); fixImportedAttributes(ip, instanceFO); instance = create(ip,GlassfishInstanceProvider.getProvider(), autoregistered); } else { LOGGER.log(Level.FINER, "GlassFish folder {0} is not a valid install.", instanceFO.getPath()); // NOI18N instanceFO.delete(); } return instance; } /** * Write GlassFish server instance data into persistent storage. *

* @param instance GlassFish server instance to be written. * @throws IOException */ public static void writeInstanceToFile( GlassfishInstance instance) throws IOException { String glassfishRoot = instance.getGlassfishRoot(); if(glassfishRoot == null) { LOGGER.log(Level.SEVERE, NbBundle.getMessage(GlassfishInstanceProvider.class, "MSG_NullServerFolder")); // NOI18N return; } String url = instance.getDeployerUri(); // For GFV3 managed instance files { FileObject dir = org.netbeans.modules.glassfish.common.utils.ServerUtils .getRepositoryDir(GlassfishInstanceProvider.getProvider() .getInstancesDirFirstName(), true); FileObject[] instanceFOs = dir.getChildren(); FileObject instanceFO = null; for (int i = 0; i < instanceFOs.length; i++) { if (url.equals(instanceFOs[i].getAttribute(GlassfishModule.URL_ATTR)) && !instanceFOs[i].getName().startsWith(GlassfishInstanceProvider.GLASSFISH_AUTOREGISTERED_INSTANCE)) { instanceFO = instanceFOs[i]; } } if(instanceFO == null) { String name = FileUtil.findFreeFileName(dir, "instance", null); // NOI18N instanceFO = dir.createData(name); } Map attrMap = instance.getProperties(); for(Map.Entry entry: attrMap.entrySet()) { String key = entry.getKey(); if(!filterKey(key)) { Object currentValue = instanceFO.getAttribute(key); if (null != currentValue && currentValue.equals(entry.getValue())) { // do nothing } else { if (key.equals(GlassfishModule.PASSWORD_ATTR)) { String serverName = attrMap.get(GlassfishModule.DISPLAY_NAME_ATTR); String userName = attrMap.get(GlassfishModule.USERNAME_ATTR); Keyring.save(GlassfishInstance.passwordKey( serverName, userName), entry.getValue().toCharArray(), "GlassFish administrator user password"); LOGGER.log(Level.FINEST, "{0} attribute stored in keyring: {1}", new String[] {instance.getDisplayName(), key}); } else { instanceFO.setAttribute(key, entry.getValue()); LOGGER.log(Level.FINEST, "{0} attribute stored: {1} = {2}", new String[] {instance.getDisplayName(), key, entry.getValue()}); } } } } // Remove FO attributes that are no more stored in server instance. for (Enumeration foAttrs = instanceFO.getAttributes(); foAttrs.hasMoreElements(); ) { String foAttr = foAttrs.nextElement(); if (!attrMap.containsKey(foAttr)) { instanceFO.setAttribute(foAttr, null); LOGGER.log(Level.FINEST, "{0} attribute deleted: {1}", new String[]{instance.getDisplayName(), foAttr}); } } instance.putProperty(INSTANCE_FO_ATTR, instanceFO.getName()); instance.getCommonSupport().setFileObject(instanceFO); } } //////////////////////////////////////////////////////////////////////////// // Instance attributes // //////////////////////////////////////////////////////////////////////////// // Server properties private boolean removable = true; /** GlassFish server properties. */ private transient Map properties; /** GlassFish server version. *

* This is always version of local GlassFish related to JavaEE platform, * even when registered domain is remote. */ private final GlassFishVersion version; /** Process information of local running server started from IDE. *

* This value shall be null when there is no server started * from IDE running. But null does not mean that server * is not running at all. */ private transient volatile Process process; /** Configuration changes listener watching domain.xml file. */ private final transient DomainXMLChangeListener domainXMLListener; private transient InstanceContent ic; private transient Lookup localLookup; private transient Lookup full; private final transient Lookup.Result lookupResult = Lookups.forPath(Util.GF_LOOKUP_PATH).lookupResult( GlassfishModuleFactory.class);; private transient Collection currentFactories = Collections.emptyList(); /** GlassFish server support API for this instance. */ private final transient CommonServerSupport commonSupport; // API instance private ServerInstance commonInstance; private GlassfishInstanceProvider instanceProvider; // GuardedBy("lookupResult") private Node fullNode; //////////////////////////////////////////////////////////////////////////// // Constructors // //////////////////////////////////////////////////////////////////////////// @SuppressWarnings("LeakingThisInConstructor") private GlassfishInstance(Map ip, GlassFishVersion version, GlassfishInstanceProvider instanceProvider, boolean prepareProperties) { this.version = version; this.process = null; ic = new InstanceContent(); localLookup = new AbstractLookup(ic); full = localLookup; this.instanceProvider = instanceProvider; String domainDirPath = ip.get(GlassfishModule.DOMAINS_FOLDER_ATTR); String domainName = ip.get(GlassfishModule.DOMAIN_NAME_ATTR); if (null != domainDirPath && null != domainName) { File domainDir = new File(domainDirPath,domainName); PortCollection pc = new PortCollection(); if (Util.readServerConfiguration(domainDir, pc)) { ip.put(GlassfishModule.ADMINPORT_ATTR, Integer.toString(pc.getAdminPort())); ip.put(GlassfishModule.HTTPPORT_ATTR, Integer.toString(pc.getHttpPort())); } domainXMLListener = new DomainXMLChangeListener(this, ServerUtils.getDomainConfigFile(domainDirPath, domainName)); } else { domainXMLListener = null; } if (prepareProperties) { this.properties = prepareProperties(ip); } else { this.properties = new Props(ip); } if (!isPublicAccess()) { // Add this instance into local lookup (to find instance from // node lookup). ic.add(this); commonInstance = ServerInstanceFactory.createServerInstance(this); } // Warn when creating instance of unknown version. if (this.version == null) { String installroot = ip.get(GlassfishModule.GLASSFISH_FOLDER_ATTR); String displayName = ip.get(GlassfishModule.DISPLAY_NAME_ATTR); WarnPanel.gfUnknownVersionWarning(displayName, installroot); LOGGER.log(Level.INFO, NbBundle.getMessage( GlassfishInstance.class, "GlassfishInstance.init.versionNull", new String[] {displayName, installroot})); } this.commonSupport = new CommonServerSupport(this); } //////////////////////////////////////////////////////////////////////////// // Getters and Setters // //////////////////////////////////////////////////////////////////////////// /** * Get GlassFish properties. *

* @return GlassFish properties. */ public Map getProperties() { return properties; } /** * Set GlassFish properties. *

* @param properties GlassFish properties to set */ public void setProperties(final Props properties) { this.properties = properties; } /** * Get local Lookup object. *

* Allow to access local lookup object in server support objects (e.g. * CommonServerSupport). *

* @return Local Lookup object. */ Lookup localLookup() { return localLookup; } /** * Get local instance provider object. *

* Allow to access local instance provider object in server support objects * (e.g. CommonServerSupport). *

* @return Local instance provider object. */ public GlassfishInstanceProvider getInstanceProvider() { return instanceProvider; } /** * Get process information of local running server started from IDE. *

* @return Process information of local running server started from IDE. */ public Process getProcess() { return process; } /** * Get GlassFish configuration file domain.xml changes * listener. *

* @return GlassFish configuration file domain.xml changes * listener. */ public DomainXMLChangeListener getDomainXMLChangeListener() { return domainXMLListener; } /** * Set process information of local running server started from IDE. *

* @param process Process information of local running server started * from IDE. */ public void setProcess(final Process process) { this.process = process; } /** * Reset process information of local running server started from IDE. *

* Value of process information of local running server started from IDE * is set to null. */ public void resetProcess() { this.process = null; } //////////////////////////////////////////////////////////////////////////// // Fake Getters from GlassFishServer interface // //////////////////////////////////////////////////////////////////////////// /** * Get GlassFish display name stored properties. *

* @return GlassFish display name. */ @Override public String getName() { return properties.get(GlassfishModule.DISPLAY_NAME_ATTR); } /** * Get GlassFish server host from stored properties. *

* @return lassFish server host. */ @Override public String getHost() { return properties.get(GlassfishModule.HOSTNAME_ATTR); } /** * Set GlassFish server host from stored properties. *

* @param host GlassFish server host to be stored. */ public void setHost(final String host) { properties.put(GlassfishModule.HOSTNAME_ATTR, host); } /** * Get GlassFish server HTTP port from stored properties. *

* @return GlassFish server HTTP port. */ @Override public int getPort() { return intProperty(GlassfishModule.HTTPPORT_ATTR); } /** * Set GlassFish server HTTP port in stored properties. *

* @param httpPort GlassFish server HTTP port to be stored. * @throws NumberFormatException if httpPort does not contain * valid integer value. */ public void setHttpPort(String httpPort) { Integer.parseInt(httpPort); properties.put(GlassfishModule.HTTPPORT_ATTR, httpPort); } /** * Set GlassFish server HTTP port in stored properties. *

* @param httpPort GlassFish server HTTP port to be stored. */ public void setHttpPort(int httpPort) { properties.put( GlassfishModule.HTTPPORT_ATTR, Integer.toString(httpPort)); } /** * Get GlassFish server administration port from stored properties. *

* @return GlassFish server administration port. */ @Override public int getAdminPort() { return intProperty(GlassfishModule.ADMINPORT_ATTR); } /** * Set GlassFish server administration port in stored properties. *

* @param adminPort GlassFish server administration port to be stored. * @throws NumberFormatException if httadminPortpPort does not contain * valid integer value. */ public void setAdminPort(String adminPort) { properties.put(GlassfishModule.ADMINPORT_ATTR, adminPort); } /** * Set GlassFish server administration port in stored properties. *

* @param adminPort GlassFish server administration port to be stored. */ public void setAdminPort(int adminPort) { properties.put( GlassfishModule.ADMINPORT_ATTR, Integer.toString(adminPort)); } /** * Get GlassFish server administration user name from stored properties. *

* @return GlassFish server administration user name. */ @Override public String getAdminUser() { return properties.get(GlassfishModule.USERNAME_ATTR); } /** * Get GlassFish server administration user's password from * stored properties. *

* @return GlassFish server administration user's password. */ @Override public String getAdminPassword() { return properties.get(GlassfishModule.PASSWORD_ATTR); } /** * Get GlassFish server domains folder from stored properties. *

* @return GlassFish server domains folder. */ @Override public String getDomainsFolder() { return properties.get(GlassfishModule.DOMAINS_FOLDER_ATTR); } /** * Set GlassFish server domains folder into stored properties. *

* @param domainsFolder GlassFish server domains folder. * @return Previous value of domains folder or null if there * was no value of domains folder stored. */ public String setDomainsFolder(String domainsFolder) { return properties.put(GlassfishModule.DOMAINS_FOLDER_ATTR, domainsFolder); } /** * Set GlassFish server domain name from stored properties. *

* @param domainsFolder GlassFish server domain name. */ @Override public String getDomainName() { return properties.get(GlassfishModule.DOMAIN_NAME_ATTR); } /** * Get GlassFish server target in domain (cluster or standalone * server name). *

* @return GlassFish server target in domain (cluster or standalone * server name). */ public String getTarget() { return properties.get(GlassfishModule.TARGET_ATTR); } /** * Set GlassFish server target in domain (cluster or standalone * server name). *

* @param target GlassFish server target in domain (cluster or standalone * server name). * @return Previous value of target or null if there * was no value of domains folder stored. */ public String setTarget(final String target) { return properties.put(GlassfishModule.TARGET_ATTR, target); } /** * Get GlassFish server URL from stored properties. *

* @return GlassFish server URL. */ @Override public String getUrl() { return properties.get(GlassfishModule.URL_ATTR); } /** * Get GlassFish server home. *

* @return Server home. */ @Override public String getServerHome() { return properties.get(GlassfishModule.GLASSFISH_FOLDER_ATTR); } /** * Get GlassFish server installation root. *

* @return Server installation root. */ @Override public String getServerRoot() { return properties.get(GlassfishModule.INSTALL_FOLDER_ATTR); } /** * Get GlassFish server version. *

* This is always version of local GlassFish related to JavaEE platform, * even when registered domain is remote. *

* @return GlassFish server version or null when version is * not known. */ @Override public GlassFishVersion getVersion() { return version; } /** * Get GlassFish server administration interface type. *

* @return GlassFish server administration interface type. */ @Override public GlassFishAdminInterface getAdminInterface() { // if (version.ordinal() < GlassFishVersion.GF_4.ordinal()) return GlassFishAdminInterface.HTTP; // else // return GlassFishAdminInterface.REST; } //////////////////////////////////////////////////////////////////////////// // Fake Getters and Setters // //////////////////////////////////////////////////////////////////////////// /** * Get information if this GlassFish server instance is local or remote. *

* Local GlassFish server instance has domains folder attribute set while * remote does not. *

* @return Value of true when this GlassFish server instance * is remote or false otherwise. */ @Override public boolean isRemote() { return properties.get(GlassfishModule.DOMAINS_FOLDER_ATTR) == null; } /** * Returns property value to which the specified key is mapped, * or null if this map contains no mapping for the * key. *

* @param key GlassFish property key. * @return GlassFish property or null if no value with * given key is stored. */ public String getProperty(String key) { return properties.get(key); } /** * Associates the specified value with the specified * key in this map. *

* If the map previously contained a mapping for the key, the old value * is replaced by the specified value. *

* @param key GlassFish property key. * @param value GlassFish property value. * @return Previous value associated with key, or * null if there was no mapping for key. */ public String putProperty(String key, String value) { return properties.put(key, value); } /** * Removes the mapping for a key from this map if it is present. *

* @param key GlassFish property key. * @return Previous value associated with key, or * null if there was no mapping for key. */ public String removeProperty(String key) { return properties.remove(key); } /** * Get GlassFish server port from stored properties. *

* @return GlassFish server port as String. */ public String getHttpPort() { return properties.get(GlassfishModule.HTTPPORT_ATTR); } /** * Get GlassFish server administration port from stored properties. *

* @return GlassFish server administration port as String. */ public String getHttpAdminPort() { return properties.get(GlassfishModule.ADMINPORT_ATTR); } /** * Set GlassFish server administration user name from stored properties. *

* Method {@see #writeInstanceToFile(GlassfishInstance)} must be called * to persist value. *

* @param usern GlassFish server administration user name. */ public void setAdminUser(final String user) { properties.put(GlassfishModule.USERNAME_ATTR, user); } /** * Store password attribute into GlassFish instance properties. *

* Password is not stored in {@see Keyring}. Method * {@see #writeInstanceToFile(GlassfishInstance)} must be called to persist * value. *

* @param password Password attribute to store. */ public void setAdminPassword(String password) { properties.put(GlassfishModule.PASSWORD_ATTR, password); } /** * Retrieve password attribute from stored properties and NetBeans * key store. *

* @return Retrieved password attribute. */ public String getPassword() { return properties.get(GlassfishModule.PASSWORD_ATTR); } public String getInstallRoot() { return properties.get(GlassfishModule.INSTALL_FOLDER_ATTR); } public String getGlassfishRoot() { return properties.get(GlassfishModule.GLASSFISH_FOLDER_ATTR); } @Override public String getDisplayName() { return properties.get(GlassfishModule.DISPLAY_NAME_ATTR); } public String getDeployerUri() { return properties.get(GlassfishModule.URL_ATTR); } public String getUserName() { return properties.get(GlassfishModule.USERNAME_ATTR); } /** * Returns Java SE platform home configured for GlassFfish server. *

* @return Java SE platform configured for GlassFfish server or null * if no such platform was configured. */ public String getJavaHome() { return properties.get(GlassfishModule.JAVA_PLATFORM_ATTR); } /** * Sets Java SE platform home configured for GlassFfish server. *

* Java SE platform home value is cleared when javahome * is null. *

* @param javahome Java SE platform home to be set for GlassFfish server. */ public void setJavaHome(String javahome) { if (javahome != null) properties.put(GlassfishModule.JAVA_PLATFORM_ATTR, javahome); else properties.remove(GlassfishModule.JAVA_PLATFORM_ATTR); } /** * Return server JVM mode as String value. *

* @return Server JVM mode. */ public String getJvmModeAsString() { return properties.get(GlassfishModule.JVM_MODE); } /** * Return server JVM mode. *

* @return Server JVM mode. */ public GlassFishJvmMode getJvmMode() { return GlassFishJvmMode.toValue( properties.get(GlassfishModule.JVM_MODE)); } /** * Return server debug port to be used to attach debugger. *

* Value of GlassfishModule.USE_SHARED_MEM_ATTR is changed * to false. *

* @return Server debug port. */ public int getDebugPort() { int debugPort; try { debugPort = Integer.parseInt( getProperty(GlassfishModule.DEBUG_PORT)); if (debugPort < LOWEST_USER_PORT || debugPort > 65535) { putProperty(GlassfishModule.DEBUG_PORT, Integer.toString(DEFAULT_DEBUG_PORT)); debugPort = DEFAULT_DEBUG_PORT; LOGGER.log(Level.INFO, "Converted debug port to {0} for {1}", new String[] {Integer.toString(DEFAULT_DEBUG_PORT), getDisplayName()}); } } catch (NumberFormatException nfe) { putProperty(GlassfishModule.DEBUG_PORT, Integer.toString(DEFAULT_DEBUG_PORT)); debugPort = DEFAULT_DEBUG_PORT; LOGGER.log(Level.INFO, "Converted debug port to {0} for {1}", new String[]{Integer.toString(DEFAULT_DEBUG_PORT), getDisplayName()}); } finally { putProperty(GlassfishModule.USE_SHARED_MEM_ATTR, Boolean.toString(false)); } return debugPort; } /** * Check if local running server started from IDE is still running. *

* @returns Value of true when process information is stored * and process is still running or false otherwise. */ public boolean isProcessRunning() { if (process == null) { return false; } try { process.exitValue(); } catch (IllegalThreadStateException itse) { return true; } return false; } /** * Returns Java SE platform {@see JavaPlatform} object configured * for GlassFfish server. *

* Current code is not optimal. It does full scan of installed platforms * to search for platform installation folder matching java home folder * from GlassFfish server instance object. *

* @return Returns Java SE platform {@see JavaPlatform} object configured * for GlassFfish server or null if no such platform was configured. */ public JavaPlatform getJavaPlatform() { String javaHome = getJavaHome(); if (javaHome == null || javaHome.length() == 0) { return null; } JavaPlatform[] platforms = JavaPlatformManager.getDefault().getInstalledPlatforms(); File javaHomeFile = new File(javaHome); JavaPlatform javaPlatform = null; for (JavaPlatform platform : platforms) { for (FileObject fo : platform.getInstallFolders()) { if (javaHomeFile.equals(FileUtil.toFile(fo))) { javaPlatform = platform; break; } } if (javaPlatform != null) { break; } } return javaPlatform; } /** * Get domains root folder with write access. *

* @return Domains root folder with write access. */ public synchronized String getDomainsRoot() { String retVal = getDomainsFolder(); if (null == retVal) { return null; } File candidate = new File(retVal); if (candidate.exists() && !Utils.canWrite(candidate)) { // we need to do some surgury here... String domainsFolder = org.netbeans.modules.glassfish.common.utils .ServerUtils.getDomainsFolder(this); String foldername = FileUtil.findFreeFolderName( FileUtil.getConfigRoot(), domainsFolder); FileObject destdir = null; try { destdir = FileUtil.createFolder(FileUtil.getConfigRoot(),foldername); } catch (IOException ex) { LOGGER.log(Level.INFO,"could not create a writable domain dir",ex); // NOI18N } if (null != destdir) { candidate = new File(candidate, getDomainName()); FileObject source = FileUtil.toFileObject(FileUtil.normalizeFile(candidate)); try { Utils.doCopy(source, destdir); retVal = FileUtil.toFile(destdir).getAbsolutePath(); setDomainsFolder(retVal); } catch (IOException ex) { // need to try again... since the domain is probably unreadable. foldername = FileUtil.findFreeFolderName( FileUtil.getConfigRoot(), domainsFolder); // NOI18N try { destdir = FileUtil.createFolder(FileUtil.getConfigRoot(), foldername); } catch (IOException ioe) { LOGGER.log(Level.INFO,"could not create a writable second domain dir",ioe); // NOI18N return retVal; } File destdirFile = FileUtil.toFile(destdir); setDomainsFolder(destdirFile.getAbsolutePath()); retVal = destdirFile.getAbsolutePath(); // getProvider() eventually creates a call to getDomainsRoot()... which can lead to a deadlock // forcing the call to happen after getDomainsRoot returns will // prevent the deadlock. RequestProcessor.getDefault().post(new Runnable() { @Override public void run() { CreateDomain cd = new CreateDomain("anonymous", "", // NOI18N new File(getServerHome()), properties, GlassfishInstanceProvider.getProvider(), false, true, "INSTALL_ROOT_KEY"); // NOI18N cd.start(); } }, 100); } } } return retVal; } //////////////////////////////////////////////////////////////////////////// // Methods dependent on linked CommonServerSupport instance // //////////////////////////////////////////////////////////////////////////// // It was too complicated to remove this dependency completely. All // // methods that are dependent on CommonServerSupport instance were marked // // as deprecated. // // All of them should be moved to CommonServerSupport class itself and // // used in context of this class in the future. // //////////////////////////////////////////////////////////////////////////// /** * Get CommonServerSupport instance associated with * this object. *

* @return CommonServerSupport instance associated with * this object. */ public final CommonServerSupport getCommonSupport() { return commonSupport; } /** * Get GlassFish server state. *

* Server state is refreshed if actual state is unknown. *

* @return GlassFish server state. * @deprecated GlassfishInstance class should not be dependent * on CommonServerSupport. */ @Deprecated public final ServerState getServerState() { return getCommonSupport().getServerState(); } /** * Stop GlassFish instance if it was started by IDE. *

* @param timeout Time to wait for successful completion. * @deprecated GlassfishInstance class should not be dependent * on CommonServerSupport. */ @Deprecated final void stopIfStartedByIde(long timeout) { if(commonSupport.isStartedByIde()) { ServerState state = commonSupport.getServerState(); if(state == ServerState.STARTING || (state == ServerState.RUNNING && GlassFishState.isOnline(this))) { try { Future stopServerTask = commonSupport.stopServer(null); if(timeout > 0) { TaskState opState = stopServerTask.get(timeout, TimeUnit.MILLISECONDS); if(opState != TaskState.COMPLETED) { Logger.getLogger("glassfish").info("Stop server failed..."); // NOI18N } } } catch(TimeoutException ex) { LOGGER.log(Level.FINE, "Server {0} timed out sending stop-domain command.", getDeployerUri()); // NOI18N } catch(Exception ex) { LOGGER.log(Level.INFO, ex.getLocalizedMessage(), ex); // NOI18N } } } else { // prevent j2eeserver from stoping an authenticated server that // it did not start. commonSupport.disableStop(); } } //////////////////////////////////////////////////////////////////////////// // Methods // //////////////////////////////////////////////////////////////////////////// /** * Build and update copy of GlassFish properties to be stored * in this object. *

* Constructor helper method. *

* @param properties Source GlassFish properties. * @return Updated copy of GlassFish properties to be stored. */ private Map prepareProperties( Map properties) { boolean isRemote = properties.get(GlassfishModule.DOMAINS_FOLDER_ATTR) == null; String deployerUri = properties.get(GlassfishModule.URL_ATTR); updateString(properties, GlassfishModule.HOSTNAME_ATTR, DEFAULT_HOST_NAME); updateString(properties, GlassfishModule.GLASSFISH_FOLDER_ATTR, ""); updateInt(properties, GlassfishModule.HTTPPORT_ATTR, DEFAULT_HTTP_PORT); updateString(properties, GlassfishModule.DISPLAY_NAME_ATTR, "Bogus display name"); updateInt(properties, GlassfishModule.ADMINPORT_ATTR, DEFAULT_ADMIN_PORT); updateString(properties, GlassfishModule.SESSION_PRESERVATION_FLAG, "true"); updateString(properties, GlassfishModule.START_DERBY_FLAG, isRemote ? "false" : "true"); updateString(properties, GlassfishModule.USE_IDE_PROXY_FLAG, "true"); updateString(properties, GlassfishModule.DRIVER_DEPLOY_FLAG, "true"); updateString(properties, GlassfishModule.HTTPHOST_ATTR, "localhost"); properties.put(GlassfishModule.JVM_MODE, isRemote && !deployerUri.contains("deployer:gfv3ee6wc") ? GlassfishModule.DEBUG_MODE : GlassfishModule.NORMAL_MODE); updateString(properties, GlassfishModule.USERNAME_ATTR, DEFAULT_ADMIN_NAME); updateString(properties, GlassfishModule.NB73_IMPORT_FIXED, Boolean.toString(true)); Map newProperties = new Props(properties); // Asume a local instance is in NORMAL_MODE // Assume remote Prelude and 3.0 instances are in DEBUG (we cannot change them) // Assume a remote 3.1 instance is in NORMAL_MODE... we can restart it into debug mode // XXX username/password handling at some point. return newProperties; } /** * Check if this instance is publicly accessible. *

* @return true if this instance is publicly accessible * or false otherwise. */ private boolean isPublicAccess() { return instanceProvider.getInternalInstance(getUrl()) != null; } /** * Make this instance publicly accessible if it was not done yet. *

* Used during initialization phase to register this object into * GlassfishInstanceProvider. * CommonServerSupport instance related to this object must be * also initialized. */ private void allowPublicAccess() { if (!isPublicAccess()) { instanceProvider.addServerInstance(this); } } /** * Get property storedValue with given name as int * storedValue. *

* Works for positive values only because -1 storedValue is reserved * for error conditions. *

* @param name Name of property to be retrieved. * @return Property storedValue as int or -1 * if property cannot be converted to integer storedValue. */ private int intProperty(String name) { String property = properties.get(name); if (property == null) { LOGGER.log(Level.WARNING, "Cannot convert null value to a number"); return -1; } try { return Integer.parseInt(property); } catch (NumberFormatException nfe) { LOGGER.log(Level.WARNING, "Cannot convert "+ property +" to a number: ", nfe); return -1; } } private void updateFactories() { // !PW FIXME should read asenv.bat on windows. Properties asenvProps = new Properties(); String homeFolder = getGlassfishRoot(); File asenvConf = new File(homeFolder, "config/asenv.conf"); // NOI18N if(asenvConf.exists()) { InputStream is = null; try { is = new BufferedInputStream(new FileInputStream(asenvConf)); asenvProps.load(is); } catch(FileNotFoundException ex) { LOGGER.log(Level.WARNING, null, ex); // NOI18N } catch(IOException ex) { LOGGER.log(Level.WARNING, null, ex); // NOI18N asenvProps.clear(); } finally { if(is != null) { try { is.close(); } catch (IOException ex) { } } } } else { LOGGER.log(Level.WARNING, "{0} does not exist", asenvConf.getAbsolutePath()); // NOI18N } Set added = new HashSet<>(); //Set removed = new HashSet(); synchronized (lookupResult) { Collection factories = lookupResult.allInstances(); added.addAll(factories); added.removeAll(currentFactories); currentFactories = factories; List proxies = new ArrayList<>(); proxies.add(localLookup); for (GlassfishModuleFactory moduleFactory : added) { if(moduleFactory.isModuleSupported(homeFolder, asenvProps)) { Object t = moduleFactory.createModule(localLookup); if (null == t) { LOGGER.log(Level.WARNING, "{0} created a null module", moduleFactory); // NOI18N } else { ic.add(t); if (t instanceof Lookup.Provider) { proxies.add(Lookups.proxy((Lookup.Provider) t)); } } } } if (!proxies.isEmpty()) { full = new ProxyLookup(proxies.toArray(new Lookup[proxies.size()])); } } } @Override public void resultChanged(LookupEvent ev) { updateFactories(); } public ServerInstance getCommonInstance() { return commonInstance; } @Override public Lookup getLookup() { synchronized (lookupResult) { return full; } } // ------------------------------------------------------------------------ // ServerInstance interface implementation // ------------------------------------------------------------------------ // TODO -- this should be done differently @Override public String getServerDisplayName() { return NbBundle.getMessage(GlassfishInstance.class, "STR_SERVER_NAME", new Object[] {version != null ? version.toString() : ""}); } @Override public Node getFullNode() { Logger.getLogger("glassfish").finer("Creating GF Instance node [FULL]"); // NOI18N synchronized (lookupResult) { if (fullNode == null) { fullNode = new Hk2InstanceNode(this, true); } return fullNode; } } @Override public Node getBasicNode() { Logger.getLogger("glassfish").finer("Creating GF Instance node [BASIC]"); // NOI18N return new Hk2InstanceNode(this, false); } @Override public JComponent getCustomizer() { return new GlassFishPropertiesCustomizer(this, localLookup); } @Override public boolean isRemovable() { return removable; } @Override public void remove() { // Just in case... if(!removable) { return; } // !PW FIXME Remove debugger hooks, if any // DebuggerManager.getDebuggerManager().removeDebuggerListener(debuggerStateListener); stopIfStartedByIde(3000L); // close the server io window String uri = getDeployerUri(); InputOutput io = LogViewMgr.getServerIO(uri); if(io != null && !io.isClosed()) { io.closeInputOutput(); } Collection lookupAll = localLookup.lookupAll(RemoveCookie.class); for(RemoveCookie cookie: lookupAll) { cookie.removeInstance(getDeployerUri()); } instanceProvider.removeServerInstance(this); ic.remove(this); } // // watch out for the localhost alias. // @Override public boolean equals(Object obj) { if (!(obj instanceof GlassfishInstance)) { return false; } GlassfishInstance other = (GlassfishInstance) obj; if (null == getDeployerUri()) { return false; } if (null == other.getDeployerUri()) { return false; } // Domain name can be null so we shall avoid NPE. boolean domainName = Objects.equals(getDomainName(), other.getDomainName()); // Domains root can be null so we shall avoid NPE. boolean domainsRoot = Objects.equals(getDomainsRoot(), other.getDomainsRoot()); return domainName && domainsRoot && getDeployerUri().replace("127.0.0.1", "localhost") .equals(other.getDeployerUri().replace("127.0.0.1", "localhost")) && getHttpPort().equals(other.getHttpPort()); } /** * Generate hash code for GlassFish instance data object. *

* Hash code is based on name attribute * (GlassfishModule.DISPLAY_NAME_ATTR property) which * is unique. *

* @return Hash code for GlassFish instance data object. */ @Override public int hashCode() { return getName().hashCode(); } }