blob: ae15f4e28b141c119223a9f25e9d8bf4c1105642 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.glassfish.javaee;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.modules.glassfish.tooling.data.GlassFishServer;
import org.netbeans.api.project.libraries.Library;
import org.netbeans.api.project.libraries.LibraryManager;
import org.netbeans.modules.j2ee.deployment.plugins.api.InstanceProperties;
import org.netbeans.modules.glassfish.spi.GlassfishModule;
import org.netbeans.modules.glassfish.spi.GlassfishModuleFactory;
import org.netbeans.modules.glassfish.spi.RegisteredDerbyServer;
import org.netbeans.modules.glassfish.spi.ServerUtilities;
import org.netbeans.modules.glassfish.tooling.data.GlassFishVersion;
import org.netbeans.modules.j2ee.deployment.plugins.api.InstanceCreationException;
import org.netbeans.spi.project.libraries.LibraryTypeProvider;
import org.netbeans.spi.project.libraries.support.LibrariesSupport;
import org.openide.filesystems.FileUtil;
import org.openide.modules.InstalledFileLocator;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
import org.openide.util.Utilities;
/**
*
* @author Peter Williams
*/
public class JavaEEServerModuleFactory implements GlassfishModuleFactory {
private static final JavaEEServerModuleFactory singleton = new JavaEEServerModuleFactory();
private static final Logger LOG = Logger.getLogger(JavaEEServerModuleFactory.class.getName());
private JavaEEServerModuleFactory() {
}
public static GlassfishModuleFactory getDefault() {
return singleton;
}
@Override
public boolean isModuleSupported(String glassfishHome, Properties asenvProps) {
// Do some moderate sanity checking to see if this v3 build looks ok.
File jar = ServerUtilities.getJarName(glassfishHome, ServerUtilities.GFV3_JAR_MATCHER);
if (jar==null) {
return false;
}
if (jar.exists()) {
return true;
}
return false;
}
private static final RequestProcessor RP = new RequestProcessor("JavaEEServerModuleFactory");
@Override
public Object createModule(Lookup instanceLookup) {
// When creating JavaEE support, also ensure this instance is added to j2eeserver
InstanceProperties ip = null;
final GlassfishModule commonModule
= instanceLookup.lookup(GlassfishModule.class);
if(commonModule != null) {
Map<String, String> props = commonModule.getInstanceProperties();
String url = props.get(InstanceProperties.URL_ATTR);
ip = InstanceProperties.getInstanceProperties(url);
if (ip == null) {
String username = props.get(InstanceProperties.USERNAME_ATTR);
// Password shall not be read from keyring during initialization
String password = null;
String displayName = props.get(InstanceProperties.DISPLAY_NAME_ATTR);
try {
ip = InstanceProperties.createInstancePropertiesNonPersistent(
url, username, password, displayName, props);
} catch (InstanceCreationException ex) {
// the initialization delay of the ServerRegistry may have triggered a ignorable
// exception
ip = InstanceProperties.getInstanceProperties(url);
if (null == ip) {
LOG.log(Level.WARNING, null, ex); // NOI18N
}
}
if(ip == null) {
LOG.log(Level.INFO, "Unable to create/locate J2EE InstanceProperties for {0}", url);
}
}
final String glassfishRoot = commonModule.getInstanceProperties().get(
GlassfishModule.GLASSFISH_FOLDER_ATTR);
final String installRoot = commonModule.getInstanceProperties().get(
GlassfishModule.INSTALL_FOLDER_ATTR);
RP.post(new Runnable() {
@Override
public void run() {
ensureEclipseLinkSupport(glassfishRoot);
ensureCometSupport(glassfishRoot);
ensureGlassFishApiSupport(commonModule.getInstance());
// lookup the javadb register service here and use it.
RegisteredDerbyServer db = Lookup.getDefault().lookup(RegisteredDerbyServer.class);
if (null != db && null != installRoot) {
File ir = new File(installRoot);
File f = new File(ir,"javadb");
if (f.exists() && f.isDirectory() && f.canRead()) {
db.initialize(f.getAbsolutePath());
}
}
}
});
} else {
LOG.log(Level.WARNING, "commonModule is NULL");
}
return (ip != null) ? new JavaEEServerModule(instanceLookup, ip) : null;
}
private static final String CLASS_LIBRARY_TYPE = "j2se"; // NOI18N
private static final String CLASSPATH_VOLUME = "classpath"; // NOI18N
private static final String SOURCE_VOLUME = "src"; // NOI18N
private static final String JAVADOC_VOLUME = "javadoc"; // NOI18N
private static final String ECLIPSE_LINK_LIB = "EclipseLink-GlassFish-v3-Prelude"; // NOI18N
private static final String ECLIPSE_LINK_LIB_2 = "EclipseLink-GlassFish-v3"; // NOI18N
private static final String EL_CORE_JAR_MATCHER = "eclipselink-wrapper" + ServerUtilities.GFV3_VERSION_MATCHER; // NOI18N
private static final String PERSISTENCE_API_JAR_MATCHER_1 = "javax.javaee" + ServerUtilities.GFV3_VERSION_MATCHER; // NOI18N
private static final String PERSISTENCE_API_JAR_MATCHER_2 = "javax.persistence" + ServerUtilities.GFV3_VERSION_MATCHER; // NOI18N
private static final String PERSISTENCE_JAVADOC = "javaee-doc-api.jar"; // NOI18N
private static boolean ensureEclipseLinkSupport(String installRoot) {
List<URL> libraryList = new ArrayList<URL>();
List<URL> docList = new ArrayList<URL>();
try {
File f = ServerUtilities.getJarName(installRoot, EL_CORE_JAR_MATCHER);
if (f != null && f.exists()) {
libraryList.add(ServerUtilities.fileToUrl(f));
} else {// we are in the final V3 Prelude jar name structure
// find the org.eclipse.persistence*.jar files and add them
for (File candidate : new File(installRoot, "modules").listFiles()) {// NOI18N
if (candidate.getName().indexOf("org.eclipse.persistence") != -1) {// NOI18N
libraryList.add(ServerUtilities.fileToUrl(candidate));
}
}
}
f = ServerUtilities.getJarName(installRoot, PERSISTENCE_API_JAR_MATCHER_1);
if (f != null && f.exists()) {
libraryList.add(ServerUtilities.fileToUrl(f));
} else {
f = ServerUtilities.getJarName(installRoot, PERSISTENCE_API_JAR_MATCHER_2);
if (f != null && f.exists()) {
libraryList.add(ServerUtilities.fileToUrl(f));
}
}
File j2eeDoc = InstalledFileLocator.getDefault().locate(
"docs/" + PERSISTENCE_JAVADOC,
Hk2LibraryProvider.JAVAEE_DOC_CODE_BASE, false);
if (j2eeDoc != null) {
docList.add(ServerUtilities.fileToUrl(j2eeDoc));
} else {
LOG.log(Level.WARNING, "Warning: Java EE documentation not found when registering EclipseLink library.");
}
} catch (MalformedURLException ex) {
LOG.log(Level.WARNING, ex.getLocalizedMessage(), ex);
return false;
}
String name = ECLIPSE_LINK_LIB;
File f = ServerUtilities.getJarName(installRoot, "gmbal" + ServerUtilities.GFV3_VERSION_MATCHER);
if (f != null && f.exists()) {
name = ECLIPSE_LINK_LIB_2;
}
return addLibrary(name, libraryList, docList,
NbBundle.getMessage(JavaEEServerModuleFactory.class, "DNAME_GF_ECLIPSELINK"), // NOI18N
NbBundle.getMessage(JavaEEServerModuleFactory.class, "DESC_GF_ECLIPSELINK")); // NOI18N
}
private static final String COMET_LIB = "Comet-GlassFish-v3-Prelude"; // NOI18N
private static final String COMET_LIB_2 = "Comet-GlassFish-v3"; // NOI18N
private static final String COMET_JAR_MATCHER = "grizzly-module" + ServerUtilities.GFV3_VERSION_MATCHER; // NOI18N
private static final String COMET_JAR_2_MATCHER = "grizzly-comet" + ServerUtilities.GFV3_VERSION_MATCHER; // NOI18N
private static final String GRIZZLY_OPTIONAL_JAR_MATCHER = "grizzly-optional" + ServerUtilities.GFV3_VERSION_MATCHER; // NOI18N
private static boolean ensureCometSupport(String installRoot) {
List<URL> libraryList = new ArrayList<URL>();
String name = COMET_LIB;
File f = ServerUtilities.getJarName(installRoot, GRIZZLY_OPTIONAL_JAR_MATCHER);
if (f == null || !f.exists()) {
f = ServerUtilities.getJarName(installRoot, COMET_JAR_MATCHER);
}
if (f == null || !f.exists()) {
name = COMET_LIB_2;
f = ServerUtilities.getJarName(installRoot, COMET_JAR_2_MATCHER);
}
if (f != null && f.exists()) {
try {
libraryList.add(ServerUtilities.fileToUrl(f));
} catch (MalformedURLException ex) {
LOG.log(Level.WARNING, ex.getLocalizedMessage(), ex);
return false;
}
}
return addLibrary(name, libraryList, null,
NbBundle.getMessage(JavaEEServerModuleFactory.class, "DNAME_GF_COMET"), // NOI18N
NbBundle.getMessage(JavaEEServerModuleFactory.class, "DESC_GF_COMET")); // NOI18N
}
private static final String JERSEY_GF_SERVER = "jersey-gf-server"; //NOI18N
private static final String[] JAXRS_LIBRARIES =
{"jackson-asl", "jackson-core-asl", "jersey-bundle", "jersey-gf-bundle", "jersey-multipart", "jettison", "mimepull", "jsr311-api"}; //NOI18N
private static final String[] JAXRS_LIBRARIES_31 =
{"jackson-core-asl", "jackson-jaxrs", "jackson-mapper-asl", "jersey-client", "jersey-core", JERSEY_GF_SERVER, "jersey-json", "jersey-multipart", "jettison", "mimepull"}; //NOI18N
private static final String JAVA_EE_6_LIB = "Java-EE-GlassFish-v3"; // NOI18N
private static final String JAVA_EE_5_LIB = "Java-EE-GlassFish-v3-Prelude"; // NOI18N
private static final String JAVA_EE_JAVADOC = "javaee-doc-api.jar"; // NOI18N
private static final String JAKARTA_EE_8_JAVADOC = "jakartaee8-doc-api.jar"; // NOI18N
private static final String JAKARTA_EE_9_JAVADOC = "jakartaee9-doc-api.jar"; // NOI18N
private static final String JAKARTA_EE_10_JAVADOC = "jakartaee10-doc-api.jar"; // NOI18N
private static boolean ensureGlassFishApiSupport(GlassFishServer server) {
String installRoot = server.getServerRoot();
List<URL> libraryList = Hk2LibraryProvider.getProvider(server).getJavaEEClassPathURLs();
List<URL> docList = new ArrayList<URL>();
String name = JAVA_EE_5_LIB;
File f = ServerUtilities.getJarName(installRoot, "gmbal" + ServerUtilities.GFV3_VERSION_MATCHER);
if (f != null && f.exists()) {
name = JAVA_EE_6_LIB;
}
File j2eeDoc;
if (GlassFishVersion.ge(server.getVersion(), GlassFishVersion.GF_7_0_0)) {
j2eeDoc = InstalledFileLocator.getDefault().locate(
"docs/" + JAKARTA_EE_10_JAVADOC,
Hk2LibraryProvider.JAVAEE_DOC_CODE_BASE, false);
} else if (GlassFishVersion.ge(server.getVersion(), GlassFishVersion.GF_6)) {
j2eeDoc = InstalledFileLocator.getDefault().locate(
"docs/" + JAKARTA_EE_9_JAVADOC,
Hk2LibraryProvider.JAVAEE_DOC_CODE_BASE, false);
} else if (GlassFishVersion.ge(server.getVersion(), GlassFishVersion.GF_5_1_0)) {
j2eeDoc = InstalledFileLocator.getDefault().locate(
"docs/" + JAKARTA_EE_8_JAVADOC,
Hk2LibraryProvider.JAVAEE_DOC_CODE_BASE, false);
} else {
j2eeDoc = InstalledFileLocator.getDefault().locate(
"docs/" + JAVA_EE_JAVADOC,
Hk2LibraryProvider.JAVAEE_DOC_CODE_BASE, false);
}
if (j2eeDoc != null) {
try {
docList.add(ServerUtilities.fileToUrl(j2eeDoc));
} catch (MalformedURLException ex) {
LOG.log(Level.INFO, "Problem while registering Java EE API library JavaDoc."); // NOI18N
}
} else {
LOG.log(Level.INFO, "Java EE documentation not found when registering Java EE API library."); // NOI18N
}
// additional jar for glassfish-samples support
f = ServerUtilities.getJarName(installRoot, "web-core" + ServerUtilities.GFV3_VERSION_MATCHER);
if (f != null && f.exists()) {
try {
libraryList.add(ServerUtilities.fileToUrl(f));
} catch (MalformedURLException ex) {
LOG.log(Level.INFO, "Problem while registering web-core into GlassFish API library."); // NOI18N
}
}
File jerseyGFServer = ServerUtilities.getJarName(installRoot, JERSEY_GF_SERVER + ServerUtilities.GFV3_VERSION_MATCHER);
boolean isGFV31 = jerseyGFServer != null;
String[] JERSEY_LIBS = (isGFV31 ? JAXRS_LIBRARIES_31 : JAXRS_LIBRARIES);
for (String entry : JERSEY_LIBS) {
f = ServerUtilities.getJarName(installRoot, entry + ServerUtilities.GFV3_VERSION_MATCHER);
if ((f != null) && (f.exists())) {
try {
libraryList.add(
FileUtil.getArchiveRoot(Utilities.toURI(f).toURL()));
} catch (MalformedURLException ex) {
}
}
}
return addLibrary(name, libraryList, docList,
NbBundle.getMessage(JavaEEServerModuleFactory.class, "DNAME_GF_JAVA_EE_IMPL"), // NOI18N
NbBundle.getMessage(JavaEEServerModuleFactory.class, "DESC_GF_JAVA_EE_IMPL")); // NOI18N
}
private static boolean addLibrary(String name, List<URL> libraryList, List<URL> docList, String displayName, String description) {
return addLibrary(name, CLASS_LIBRARY_TYPE, libraryList, docList, displayName, description);
}
private static synchronized boolean addLibrary(String name, String libType, List<URL> libraryList, List<URL> docList, String displayName,
String description) {
LibraryManager lmgr = LibraryManager.getDefault();
int size = 0;
Library lib = lmgr.getLibrary(name);
// Verify that existing library is still valid.
if (lib != null) {
List<URL> libList = lib.getContent(CLASSPATH_VOLUME);
size = libList.size();
for (URL libUrl : libList) {
String libPath = libUrl.getFile();
// file seems to want to return a file: protocol string... not the FILE portion of the URL
if (libPath.length() > 5) {
libPath = libPath.substring(5);
}
if (!new File(libPath.replace("!/", "")).exists()) {
LOG.log(Level.FINE, "libPath does not exist. Updating {0}", name);
try {
lmgr.removeLibrary(lib);
} catch (IOException ex) {
LOG.log(Level.INFO, ex.getLocalizedMessage(), ex);
} catch (IllegalArgumentException ex) {
// Already removed somehow, ignore.
}
lib = null;
size = 0;
break;
}
}
}
// verify that there are not new components in the 'new' definition
// of the library... If there are new components... rebuild the library.
if (lib != null && size < libraryList.size()) {
try {
lmgr.removeLibrary(lib);
} catch (IOException ex) {
LOG.log(Level.INFO, ex.getLocalizedMessage(), ex);
} catch (IllegalArgumentException ex) {
// Already removed somehow, ignore.
}
lib = null;
}
if (lib != null) {
List<URL> libList = lib.getContent(JAVADOC_VOLUME);
size = libList.size();
for (URL libUrl : libList) {
String libPath = libUrl.getFile();
// file seems to want to return a file: protocol string... not the FILE portion of the URL
if (libPath.length() > 5) {
libPath = libPath.substring(5);
}
if (!new File(libPath.replace("!/", "")).exists()) {
LOG.log(Level.FINE, "libPath does not exist. Updating {0}", name);
try {
lmgr.removeLibrary(lib);
} catch (IOException ex) {
LOG.log(Level.INFO, ex.getLocalizedMessage(), ex);
} catch (IllegalArgumentException ex) {
// Already removed somehow, ignore.
}
lib = null;
size = 0;
break;
}
}
}
// verify that there are not new components in the 'new' definition
// of the library... If there are new components... rebuild the library.
if (lib != null && null != docList && size < docList.size()) {
try {
lmgr.removeLibrary(lib);
} catch (IOException ex) {
LOG.log(Level.INFO, ex.getLocalizedMessage(), ex);
} catch (IllegalArgumentException ex) {
// Already removed somehow, ignore.
}
lib = null;
}
if (lib == null) {
Map<String, List<URL>> contents;
try {
contents = new HashMap<String, List<URL>>();
if (null != libraryList) {
contents.put(CLASSPATH_VOLUME, libraryList);
}
if (null != docList) {
contents.put(JAVADOC_VOLUME, docList);
}
LibraryTypeProvider ltp = LibrariesSupport.getLibraryTypeProvider(libType);
if (null != ltp) {
lib = lmgr.createLibrary(libType, name, displayName, description, contents);
LOG.log(Level.FINE, "Created library {0}", name);
} else {
lmgr.addPropertyChangeListener(new InitializeLibrary(lmgr, libType, name, contents, displayName, description));
LOG.log(Level.FINE, "schedule to create library {0}", name);
}
} catch (IOException ex) {
// Someone must have created the library in a parallel thread, try again otherwise fail.
lib = lmgr.getLibrary(name);
if (lib == null) {
LOG.log(Level.INFO, ex.getLocalizedMessage(), ex);
}
} catch (IllegalArgumentException ex) {
// Someone must have created the library in a parallel thread, try again otherwise fail.
lib = lmgr.getLibrary(name);
if (lib == null) {
LOG.log(Level.INFO, ex.getLocalizedMessage(), ex);
}
}
}
return lib != null;
}
static class InitializeLibrary implements PropertyChangeListener {
private final LibraryManager lmgr;
private String name;
private Map<String, List<URL>> content;
private final String libType;
private final String displayName;
private final String description;
InitializeLibrary(LibraryManager lmgr, String libType, String name, Map<String, List<URL>> content,
String displayName, String description) {
this.lmgr = lmgr;
this.name = name;
this.content = content;
this.libType = libType;
this.displayName = displayName;
this.description = description;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
synchronized (singleton) {
if (null != name) {
Library l = lmgr.getLibrary(name);
final PropertyChangeListener pcl = this;
if (null == l) {
try {
LibraryTypeProvider ltp = LibrariesSupport.getLibraryTypeProvider(libType);
if (null != ltp) {
lmgr.createLibrary(libType, name, displayName, description, content);
LOG.log(Level.FINE, "Created library {0}", name);
removeFromListenerList(pcl);
}
} catch (IOException ex) {
LOG.log(Level.INFO,
ex.getLocalizedMessage(), ex);
} catch (IllegalArgumentException iae) {
LOG.log(Level.INFO,
iae.getLocalizedMessage(), iae);
}
} else {
// The library is there... and the listener is still active... hmmm.
removeFromListenerList(pcl);
}
}
}
}
private void removeFromListenerList(final PropertyChangeListener pcl) {
RP.post(new Runnable() {
@Override
public void run() {
synchronized (singleton) {
if (null != lmgr) {
lmgr.removePropertyChangeListener(pcl);
content = null;
name = null;
}
}
}
});
}
}
}