blob: cfcd17c3bd3c489894dff129319d6caf1eda3555 [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.j2ee.persistence.provider;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.netbeans.api.db.explorer.ConnectionManager;
import org.netbeans.api.db.explorer.DatabaseConnection;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.modules.j2ee.persistence.api.PersistenceLocation;
import org.netbeans.modules.j2ee.persistence.api.PersistenceScope;
import org.netbeans.modules.j2ee.persistence.dd.PersistenceUtils;
import org.netbeans.modules.j2ee.persistence.dd.common.Persistence;
import org.netbeans.modules.j2ee.persistence.dd.common.PersistenceUnit;
import org.netbeans.modules.j2ee.persistence.dd.common.Properties;
import org.netbeans.modules.j2ee.persistence.dd.common.Property;
import org.netbeans.modules.j2ee.persistence.editor.JPAEditorUtil;
import org.netbeans.modules.j2ee.persistence.spi.provider.PersistenceProviderSupplier;
import org.netbeans.modules.j2ee.persistence.spi.server.ServerStatusProvider;
import org.netbeans.modules.j2ee.persistence.spi.server.ServerStatusProvider2;
import org.netbeans.modules.j2ee.persistence.unit.*;
import org.netbeans.modules.j2ee.persistence.wizard.Util;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.util.Exceptions;
import org.openide.util.Parameters;
/**
* A utility class for handling persistence units and providers. Provides means
* for constructing a persistence unit and for getting/setting/changing
* properties of persistence units.
*
* @author Martin Adamek, Erno Mononen
*/
public class ProviderUtil {
// known providers
public static final Provider HIBERNATE_PROVIDER = new HibernateProvider(Persistence.VERSION_1_0);
public static final Provider HIBERNATE_PROVIDER2_0 = new HibernateProvider(Persistence.VERSION_2_0);
public static final Provider HIBERNATE_PROVIDER2_1 = new HibernateProvider(Persistence.VERSION_2_1);
public static final Provider TOPLINK_PROVIDER1_0 = ToplinkProvider.create(Persistence.VERSION_1_0);
public static final Provider ECLIPSELINK_PROVIDER2_0 = new EclipseLinkProvider(Persistence.VERSION_2_0);
public static final Provider ECLIPSELINK_PROVIDER = new EclipseLinkProvider(Persistence.VERSION_2_1);
public static final Provider ECLIPSELINK_PROVIDER1_0 = new EclipseLinkProvider(Persistence.VERSION_1_0);
public static final Provider KODO_PROVIDER = new KodoProvider();
public static final Provider DATANUCLEUS_PROVIDER = new DataNucleusProvider();
public static final Provider OPENJPA_PROVIDER = new OpenJPAProvider(Persistence.VERSION_2_0);
public static final Provider OPENJPA_PROVIDER2_1 = new OpenJPAProvider(Persistence.VERSION_2_1);
public static final Provider OPENJPA_PROVIDER1_0 = new OpenJPAProvider(Persistence.VERSION_1_0);
public static final Provider DEFAULT_PROVIDER = new DefaultProvider();
public static final Provider DEFAULT_PROVIDER2_0 = new DefaultProvider(Persistence.VERSION_2_0);
public static final Provider DEFAULT_PROVIDER2_1 = new DefaultProvider(Persistence.VERSION_2_1);
/**
* TopLink provider using the provider class that was used in NetBeans 5.5. Needed
* for maintaining backwards compatibility with persistence units created in 5.5.
*/
private static final Provider TOPLINK_PROVIDER_55_COMPATIBLE = ToplinkProvider.create55Compatible();
private ProviderUtil() {
}
/**
* Gets the persistence provider identified by the given <code>providerClass</code>.
* If the given class was empty or null, will return the default persistence provider
* of the given project's target server, or null if a default provider is not supported
* in the given project.
*
* @param providerClass the FQN of the class that specifies the persistence provider.
*
* @return the provider that the given providerClass represents or null if it was
* an empty string and the project doesn't suppport a default (container managed)
* persistence provider.
*/
public static Provider getProvider(String providerClass, Project project) {
if (null == providerClass || "".equals(providerClass.trim())) {
return getContainerManagedProvider(project);
}
String ver = PersistenceUtils.getJPAVersion(project);
ver = ver == null ? Persistence.VERSION_2_1 : ver;
Provider ret = null;
switch(ver) {
case Persistence.VERSION_1_0:
ret = DEFAULT_PROVIDER;
break;
case Persistence.VERSION_2_0:
ret = DEFAULT_PROVIDER2_0;
break;
case Persistence.VERSION_2_1:
ret = DEFAULT_PROVIDER2_1;
}// some unknown provider
for (Provider each : getAllProviders()) {
if (each.getProviderClass().equals(providerClass.trim())) {
ret = each;
if(ver.equals(ProviderUtil.getVersion(each)))return each;
}
}
return ret;
}
/*
* Gets the default persistence provider of the target server
* of the given <code>project</code>.
*
* @return the default container managed provider for the given project or <code>null</code>
* no default provider could be resolved.
*
* @throws NullPointerException if the given project was null.
*/
private static Provider getContainerManagedProvider(Project project) {
PersistenceProviderSupplier providerSupplier = project.getLookup().lookup(PersistenceProviderSupplier.class);
if (providerSupplier == null
|| !providerSupplier.supportsDefaultProvider()
|| providerSupplier.getSupportedProviders().isEmpty()) {
return null;
}
return providerSupplier.getSupportedProviders().get(0);
}
/**
* Gets the database connection specified in the given persistence
* unit.
*
* @param pu the persistence unit whose database connection is to
* be retrieved; must not be null.
*
* @rerturn the connection specified in the given persistence unit or
* <code>null</code> if it didn't specify a connectioh.
*
*/
public static DatabaseConnection getConnection(PersistenceUnit pu) {
Parameters.notNull("pu", pu); //NOI18N
if (pu.getProperties() == null) {
return null;
}
String url = null;
String driver = null;
String username = null;
Property[] properties = pu.getProperties().getProperty2();
Provider provider = getProvider(pu);
for (int i = 0; i < properties.length; i++) {
String key = properties[i].getName();
if (key == null) {
continue;
}
if (key.equals(provider.getJdbcUrl())) {
url = properties[i].getValue();
} else if (key.equals(provider.getJdbcDriver())) {
driver = properties[i].getValue();
} else if (key.equals(provider.getJdbcUsername())) {
username = properties[i].getValue();
}
}
DatabaseConnection[] connections = ConnectionManager.getDefault().getConnections();
for (int i = 0; i < connections.length; i++) {
DatabaseConnection c = connections[i];
// password is problematic, when it is returned?
if (c.getDatabaseURL().equals(url)
&& c.getDriverClass().equals(driver)
&& c.getUser().equals(username)) {
return c;
}
}
return null;
}
/**
* Gets the database connection properties (irl,name,password) specified in the given persistence
* unit.
*
* @param pu the persistence unit whose database connection is to
* be retrieved; must not be null.
*
* @rerturn the connection properties specified in the given persistence unit or
* <code>null</code> if it didn't specify a connectioh.
*
*/
public static HashMap<String, String> getConnectionProperties(PersistenceUnit pu) {
Parameters.notNull("pu", pu); //NOI18N
if (pu.getProperties() == null) {
return null;
}
HashMap<String, String> ret = new HashMap<String,String>();
Property[] properties = pu.getProperties().getProperty2();
Provider provider = getProvider(pu);
for (int i = 0; i < properties.length; i++) {
String key = properties[i].getName();
if (key == null) {
continue;
}
if (key.equals(provider.getJdbcUrl())) {
ret.put(JPAEditorUtil.JDBCURLKEY, properties[i].getValue());//NOI18N
} else if (key.equals(provider.getJdbcDriver())) {
ret.put(JPAEditorUtil.JDBCDRIVERKEY, properties[i].getValue());
} else if (key.equals(provider.getJdbcUsername())) {
ret.put(JPAEditorUtil.JDBCUSERKEY, properties[i].getValue());
}
}
return ret;
}
/**
* Sets the given table generation strategy for given persistence unit.
* @param persistenceUnit
* @param tableGenerationStrategy the strategy to set, see constants in <code>Provider</code>
* @project the project of the given persistence unit
*/
public static void setTableGeneration(PersistenceUnit persistenceUnit, String tableGenerationStrategy, Project project) {
String providerClass = persistenceUnit.getProvider();
Provider provider = ProviderUtil.getProvider(providerClass, project);
setTableGeneration(persistenceUnit, tableGenerationStrategy, provider);
}
/**
* Sets the given table generation strategy for the given persistence unit.
*
* @param persistenceUnit the persistenceUnit to which the given strategy is to be set.
* @param tableGenerationStrategy the strategy to set, see constants in <code>Provider</code> for
* options.
* @provider the provider whose table generation property will be used.
*/
public static void setTableGeneration(PersistenceUnit persistenceUnit, String tableGenerationStrategy, Provider provider) {
// issue 123224. The user can have a persistence.xml in J2SE project without provider specified
if (provider == null) {
return;
}
String version = Persistence.VERSION_1_0;
if (persistenceUnit instanceof org.netbeans.modules.j2ee.persistence.dd.persistence.model_2_0.PersistenceUnit) {
version = Persistence.VERSION_2_0;
} else if (persistenceUnit instanceof org.netbeans.modules.j2ee.persistence.dd.persistence.model_2_1.PersistenceUnit) {
version = Persistence.VERSION_2_1;
}
Property tableGenerationProperty = provider.getTableGenerationProperty(tableGenerationStrategy, version);
Properties properties = persistenceUnit.getProperties();
if (properties == null) {
properties = persistenceUnit.newProperties();
persistenceUnit.setProperties(properties);
}
Property existing = getProperty(properties.getProperty2(), provider.getTableGenerationPropertyName());
if (existing != null && tableGenerationProperty == null) {
properties.removeProperty2(existing);
} else if (existing != null && tableGenerationProperty != null) {
existing.setValue(tableGenerationProperty.getValue());
} else if (tableGenerationProperty != null) {
properties.addProperty2(tableGenerationProperty);
}
}
/**
* Sets the given provider, connection and table generation strategy to the given persistence unit. Note
* that if the given persistence unit already had an existing provider, its existing properties are not preserved
* with the exception of the database connection properties. In other words, you have to explicitly set for
* example a table generation strategy for the persistence unit after changing the provider.
*
* @param persistenceUnit the persistence unit to which the other params are to be set; must not be null.
* @param provider the provider to set; must not be null.
* @connection the connection to set; must not be null.
* @tableGenerationStrategy the table generation strategy to set.
*/
public static void setProvider(PersistenceUnit persistenceUnit, Provider provider,
DatabaseConnection connection, String tableGenerationStrategy) {
Parameters.notNull("persistenceUnit", persistenceUnit); //NOI18N
// See issue 123224 desc 12 and desc 15 - connection can be null
//Parameters.notNull("connection", connection); //NOI18N
Parameters.notNull("provider", provider); //NOI18N
removeProviderProperties(persistenceUnit);
persistenceUnit.setProvider(provider.getProviderClass());
setDatabaseConnection(persistenceUnit, provider, connection);
setTableGeneration(persistenceUnit, tableGenerationStrategy, provider);
}
/**
* Removes all provider specific properties from the given persistence unit.
* Should be called before setting a new provider for persistence units.
*
* @param persistenceUnit the persistence unit whose provider specific
* properties are to be removed; must not be null.
*/
public static void removeProviderProperties(PersistenceUnit persistenceUnit) {
Parameters.notNull("persistenceUnit", persistenceUnit); //NOI18N
ArrayList<Provider> olds = getProviders(persistenceUnit);
Set providersProperties = new HashSet();
for (Provider old : olds) {
providersProperties.addAll(old.getPropertyNames());
}
Property[] properties = getProperties(persistenceUnit);
for (int i = 0; i < properties.length; i++) {
Property each = properties[i];
if (providersProperties.contains(each.getName())) {
persistenceUnit.getProperties().removeProperty2(each);
}
}
persistenceUnit.setProvider(null);
}
/**
* Constructs a persistence unit based on the given paramaters. Takes care of
* setting the default vendor specific properties (if any) to the created
* persistence unit.
*
* @param name the name for the persistence unit; must not be null.
* @param provider the provider for the persitence unit; must not be null.
* @param connection the database connection for the persistence unit; must not be null.
*
* @return the created persistence unit.
*/
public static PersistenceUnit buildPersistenceUnit(String name, Provider provider, DatabaseConnection connection, String version) {
Parameters.notNull("name", name);
Parameters.notNull("provider", provider);
Parameters.notNull("connection", connection);
PersistenceUnit persistenceUnit = null;
if (Persistence.VERSION_2_1.equals(version)) {
persistenceUnit = new org.netbeans.modules.j2ee.persistence.dd.persistence.model_2_1.PersistenceUnit();
} else if (Persistence.VERSION_2_0.equals(version)) {
persistenceUnit = new org.netbeans.modules.j2ee.persistence.dd.persistence.model_2_0.PersistenceUnit();
} else {//currently default 1.0
persistenceUnit = new org.netbeans.modules.j2ee.persistence.dd.persistence.model_1_0.PersistenceUnit();
}
persistenceUnit.setName(name);
persistenceUnit.setProvider(provider.getProviderClass());
Properties properties = persistenceUnit.newProperties();
Map connectionProperties = provider.getConnectionPropertiesMap(connection, version);
for (Iterator it = connectionProperties.keySet().iterator(); it.hasNext();) {
String propertyName = (String) it.next();
Property property = properties.newProperty();
property.setName(propertyName);
property.setValue((String) connectionProperties.get(propertyName));
properties.addProperty2(property);
}
Map defaultProperties = provider.getDefaultVendorSpecificProperties();
for (Iterator it = defaultProperties.keySet().iterator(); it.hasNext();) {
String propertyName = (String) it.next();
Property property = properties.newProperty();
property.setName(propertyName);
property.setValue((String) defaultProperties.get(propertyName));
properties.addProperty2(property);
}
persistenceUnit.setProperties(properties);
return persistenceUnit;
}
/**
* Sets the properties of the given connection to the given persistence unit.
*
* @param persistenceUnit the persistence unit to which the connection properties
* are to be set. Must not be null.
* @param connection the database connections whose properties are to be set. Must
* not be null.
*/
public static void setDatabaseConnection(PersistenceUnit persistenceUnit, DatabaseConnection connection) {
setDatabaseConnection(persistenceUnit, null, connection);
}
/**
* Sets the properties of the given connection to the given persistence unit.
*
* @param persistenceUnit the persistence unit to which the connection properties
* are to be set. Must not be null.
* @param connection the database connections whose properties are to be set. Must
* not be null.
* @param provider it's persistence provider, most database connection properties are
* based on provider supported properties, if null profider is received from provider class from persistence unit.
* it's better to pass provider as differnt providers may have the same provider class.
*/
public static void setDatabaseConnection(PersistenceUnit persistenceUnit, Provider provider, DatabaseConnection connection) {
Parameters.notNull("persistenceUnit", persistenceUnit); //NOI18N
// See issue 123224 desc 12 and desc 15 - connection can be null
//Parameters.notNull("connection", connection); //NOI18N
if (provider == null) {
provider = getProvider(persistenceUnit);
}
Property[] properties = getProperties(persistenceUnit);
String version = Persistence.VERSION_1_0;
if(persistenceUnit instanceof org.netbeans.modules.j2ee.persistence.dd.persistence.model_2_1.PersistenceUnit) {// we have persistence unit with specific version, should use it
version = Persistence.VERSION_2_1;
} else if(persistenceUnit instanceof org.netbeans.modules.j2ee.persistence.dd.persistence.model_2_0.PersistenceUnit) {// we have persistence unit with specific version, should use it
version = Persistence.VERSION_2_0;
}
Map<String, String> propertiesMap = provider.getConnectionPropertiesMap(connection, version);
for (String name : propertiesMap.keySet()) {
Property property = getProperty(properties, name);
if (property == null) {
if (persistenceUnit.getProperties() == null) {
persistenceUnit.setProperties(persistenceUnit.newProperties());
}
property = persistenceUnit.getProperties().newProperty();
property.setName(name);
persistenceUnit.getProperties().addProperty2(property);
}
String value = propertiesMap.get(name);
// value must be present (setting null would cause
// value attribute to not be present)
if (value == null) {
value = "";
}
property.setValue(value);
}
}
/**
* Gets the properties of the given persistence unit. If the properties of
* given unit were null, will return an empty array.
*
* @return array of properties, empty if the given unit's properties were null.
*/
static Property[] getProperties(PersistenceUnit persistenceUnit) {
if (persistenceUnit.getProperties() != null) {
return persistenceUnit.getProperties().getProperty2();
}
return new Property[0];
}
/**
* @return the property from the given properties whose name matches
* the given propertyName
* or null if the given properties didn't contain property with a matching name.
*/
private static Property getProperty(Property[] properties, String propertyName) {
if (null == properties) {
return null;
}
for (int i = 0; i < properties.length; i++) {
Property each = properties[i];
if (each.getName() != null && each.getName().equals(propertyName)) {
return each;
}
}
return null;
}
/**
* Gets the property that matches the given <code>propertyName</code> from the
* given <code>persistenceUnit</code>.
*
* @return the matching property or null if the given persistence unit didn't
* contain a property with a matching name.
*/
public static Property getProperty(PersistenceUnit persistenceUnit, String propertyName) {
if (persistenceUnit.getProperties() == null) {
return null;
}
return getProperty(persistenceUnit.getProperties().getProperty2(), propertyName);
}
/**
* Gets the persistence provider of the given persistence unit with latest version match.
* As for now providers should be backward compartible but forward compartibility may be missed.
*
* @param persistenceUnit the persistence unit whose provider is to
* be get. Must not be null.
*
* @return the provider of the given persistence unit. In case that no specific
* provider can be resolved <code>DEFAULT_PROVIDER</code> will be returned. prvider
*/
public static Provider getProvider(PersistenceUnit persistenceUnit) {
return getProvider(persistenceUnit, getAllProviders());
}
/**
* Gets the persistence provider of the given persistence unit with latest version match if exact match isn't possible
* As for now providers should be backward compartible but forward compartibility may be missed.
*
* @param persistenceUnit the persistence unit whose provider is to
* be get. Must not be null.
*
* @return the provider of the given persistence unit. In case that no specific
* provider can be resolved <code>DEFAULT_PROVIDER</code> will be returned. prvider
*/
public static Provider getProvider(PersistenceUnit persistenceUnit, Provider[] providers) {
Parameters.notNull("persistenceUnit", persistenceUnit); //NOI18N
String version = Persistence.VERSION_1_0;
if(persistenceUnit instanceof org.netbeans.modules.j2ee.persistence.dd.persistence.model_2_1.PersistenceUnit) {// we have persistence unit with specific version, should use it
version = Persistence.VERSION_2_1;
} else if(persistenceUnit instanceof org.netbeans.modules.j2ee.persistence.dd.persistence.model_2_0.PersistenceUnit) {// we have persistence unit with specific version, should use it
version = Persistence.VERSION_2_0;
}
long top_version = Math.round(Double.parseDouble(version) * 100);
long longVersion = top_version;
Provider top_provider = null;
if (providers == null) {
providers = getAllProviders();
}
Set<Provider> candidates = new HashSet<Provider>();
for (Provider each : providers) {
if (each.getProviderClass().equals(persistenceUnit.getProvider())) {
candidates.add(each);
}
}
candidates = filterProvidersByProperties(candidates, persistenceUnit.getProperties()!=null ? persistenceUnit.getProperties().getProperty2() : null);
//
if (candidates.size() == 1) {
return candidates.iterator().next();
} else {
//unfortunatly there is no strict rule from class to provider version, but we are trying to guess best
for (Provider each : candidates) {
String provVersion = each.getVersion();
if (provVersion == null) {
//this provider do not support versioning yet
return each;
} else {
long cur_version = Math.round(Double.parseDouble(provVersion) * 100);
if (longVersion == cur_version) {
//exact match with jpa version, suppose provider to use based on persistence.xml version
top_provider = each;
top_version = cur_version;
break;
} else if (cur_version >= top_version) {
top_provider = each;
top_version = cur_version;
}
}
}
}
if(top_provider == null) {
switch(version) {
case Persistence.VERSION_1_0:
return DEFAULT_PROVIDER;
case Persistence.VERSION_2_0:
return DEFAULT_PROVIDER2_0;
default:
return DEFAULT_PROVIDER2_1;
}// some unknown provider
}
return top_provider;
}
//analize properties for best match provider version
private static Set<Provider> filterProvidersByProperties(Set<Provider> providers, Property[] properties){
Set<Provider> ret = null;
if(providers == null){}
else if(providers.size()<= 1 || properties==null || properties.length==0) ret = new HashSet(providers);
else {
ret = new HashSet(providers);
HashMap <Integer, ArrayList<Provider>> rates = new HashMap<Integer, ArrayList<Provider>>();
int lowrate = Integer.MAX_VALUE;
for(Provider each : providers){
int rate = 0;
for(Property prop: properties){
if(each.getPropertyNames().contains(prop.getName()))rate++;
}
if(rates.get(rate) == null)rates.put(rate, new ArrayList<Provider>());
rates.get(rate).add(each);
if(rate<lowrate)lowrate=rate;
}
if(rates.size()>1){
for(Provider prov:rates.get(lowrate))ret.remove(prov);
}
}
return ret;
}
/**
*
* @param provider shouldn't be null
* @return jpa version for the provider
*/
public static String getVersion(Provider provider) {
return provider.getVersion();
}
/**
* Gets the all versions of persistence providers of the given persistence unit
*
* @param persistenceUnit the persistence unit whose provider is to
* be get. Must not be null.
*
* @return the providers of the given persistence unit. In case that no specific
* provider can be resolved <code>DEFAULT_PROVIDER</code> will be returned. prvider
*/
public static ArrayList<Provider> getProviders(PersistenceUnit persistenceUnit) {
Parameters.notNull("persistenceUnit", persistenceUnit); //NOI18N
ArrayList<Provider> providers = new ArrayList<Provider>();
for (Provider each : getAllProviders()) {
if (each.getProviderClass().equals(persistenceUnit.getProvider())) {
providers.add(each);
}
}
if (providers.size() == 0) {
providers.add(DEFAULT_PROVIDER2_1);
}
return providers;
}
/**
*@return true if the given puDataObject is not null and its document is
* parseable, false otherwise.
*/
public static boolean isValid(PUDataObject puDataObject) {
return null == puDataObject ? false : puDataObject.parseDocument();
}
/**
* Gets the persistence units that are defined in the given <code>
* puDataObject</code>.
*
* @param puDataObject the PUDataObject whose persistence units are to be retrived.
*
* @return the persistence units specified in the given <code>puDataObject</code>
* or an empty array if there were no persistence units defined in it.
*/
public static PersistenceUnit[] getPersistenceUnits(PUDataObject puDataObject) {
if (puDataObject.getPersistence() == null) {
return new PersistenceUnit[0];
}
return puDataObject.getPersistence().getPersistenceUnit();
}
/**
* Renames given managed class in given persistence unit.
* @param persistenceUnit the unit that contains the class to be renamed.
* @param newName the new name of the class.
* @param oldName the name of the class to be renamed.
* @param dataObject
*
*/
public static void renameManagedClass(PersistenceUnit persistenceUnit, String newName,
String oldName, PUDataObject dataObject) {
dataObject.removeClass(persistenceUnit, oldName, false);
dataObject.addClass(persistenceUnit, newName, false);
}
/**
* Removes given managed class from given persistence unit.
* @param persistenceUnit the persistence unit from which the given class
* is to be removed.
* @param clazz fully qualified name of the class to be removed.
* @param dataObject the data object representing persistence.xml.
*/
public static void removeManagedClass(PersistenceUnit persistenceUnit, String clazz,
PUDataObject dataObject) {
dataObject.removeClass(persistenceUnit, clazz, false);
}
/**
* Adds given managed class to given persistence unit.
* @param persistenceUnit the persistence unit to which the given class
* is to be added.
* @param clazz fully qualified name of the class to be added.
* @param dataObject the data object representing persistence.xml.
*/
public static void addManagedClass(PersistenceUnit persistenceUnit, String clazz,
PUDataObject dataObject) {
dataObject.addClass(persistenceUnit, clazz, false);
}
/**
* Adds the given <code>persistenceUnit</code> to the <code>PUDataObject<code>
* of the given <code>project</code> and saves it.
* @param persistenceUnit the unit to be added
* @param project the project to which the unit is to be added.
* @throws InvalidPersistenceXmlException if the given project has an invalid persistence.xml file.
*
*/
public static void addPersistenceUnit(PersistenceUnit persistenceUnit, Project project) throws InvalidPersistenceXmlException {
addPersistenceUnit(persistenceUnit, project, null);
}
/**
* Adds the given <code>persistenceUnit</code> to the <code>PUDataObject<code>
* of the given <code>project</code>'s <code>root</code> and saves it.
* @param persistenceUnit the unit to be added
* @param project the project to which the unit is to be added.
* @param root the root to which the unit is to be added
* @throws InvalidPersistenceXmlException if the given project has an invalid persistence.xml file.
* @since 1.55
*
*/
public static void addPersistenceUnit(PersistenceUnit persistenceUnit, Project project, FileObject root) throws InvalidPersistenceXmlException {
String version = Persistence.VERSION_1_0;
if(persistenceUnit instanceof org.netbeans.modules.j2ee.persistence.dd.persistence.model_2_1.PersistenceUnit) {// we have persistence unit with specific version, should use it
version = Persistence.VERSION_2_1;
} else if(persistenceUnit instanceof org.netbeans.modules.j2ee.persistence.dd.persistence.model_2_0.PersistenceUnit) {// we have persistence unit with specific version, should use it
version = Persistence.VERSION_2_0;
}
PUDataObject pud = getPUDataObject(project, root, version);
pud.addPersistenceUnit(persistenceUnit);
pud.save();
}
/**
*Gets the <code>PUDataObject</code> associated with the given <code>fo</code>.
*
*@param fo the file object thas has an associated <code>PUDataObject</code>. Must
* not be null.
*
*@return the <code>PUDataObject</code> associated with the given <code>fo</code>.
*
*@throws IllegalArgumentException if the given <code>fo</code> is null.
*@throws InvalidPersistenceXmlException if the given file object represents
* an invalid persistence.xml file.
*/
public static PUDataObject getPUDataObject(FileObject fo) throws InvalidPersistenceXmlException {
Parameters.notNull("fo", fo); //NOI18N
DataObject dataObject = null;
try {
dataObject = DataObject.find(fo);
} catch (DataObjectNotFoundException ex) {
Exceptions.printStackTrace(ex);
}
if (!(dataObject instanceof PUDataObject)) {
throw new InvalidPersistenceXmlException(FileUtil.getFileDisplayName(fo));
}
return (PUDataObject) dataObject;
}
/**
* Gets the PUDataObject associated with the given <code>project</code>. If there
* was no PUDataObject (i.e. no persistence.xml) in the project, a new one
* will be created. Use
* {@link #getDDFile} for testing whether a project has a persistence.xml file.
*
*@param project the project whose PUDataObject is to be get. Must not be null.
*@param version if version is specified corresponding persistence.xml will be created, otherwise version will be determined from project classpath
*
*@return <code>PUDataObject</code> associated with the given project or null
* if there is no such <code>PUDataObject</code>.
*
* @throws InvalidPersistenceXmlException if the given <code>project</code> had an existing
* invalid persitence.xml file.
*/
public static synchronized PUDataObject getPUDataObject(Project project, String version) throws InvalidPersistenceXmlException {
return getPUDataObject(project, null, version);
}
/**
* Gets the PUDataObject associated with the given <code>FileObject</code> within the given <code>project</code>.
* If there was no PUDataObject (i.e. no persistence.xml) in the project associated with the given FileObject, a new one
* will be created. Use
* {@link #getDDFile(org.netbeans.api.project.Project, org.openide.filesystems.FileObject)} for testing whether a project has a persistence.xml file associated with the given FileObject.
*
*@param project the project whose PUDataObject is to be get. Must not be null.
*@param fo the FileObject whose PUDataObject is to be get.
*@param version if version is specified corresponding persistence.xml will be created, otherwise version will be determined from project classpath
*
*@return <code>PUDataObject</code> associated with the given FileObject or null
* if there is no such <code>PUDataObject</code>.
*
* @throws InvalidPersistenceXmlException if the given <code>FileObject</code> had an existing
* invalid persitence.xml file.
* @since 1.55
*/
public static synchronized PUDataObject getPUDataObject(Project project, FileObject fo, String version) throws InvalidPersistenceXmlException {
Parameters.notNull("project", project); //NOI18N
FileObject puFileObject = getDDFile(project, fo);
if (puFileObject == null) {
try {
puFileObject = createPersistenceDDFile(project, fo, version);
} catch (IOException e) {
Exceptions.printStackTrace(e);
}
}
if (puFileObject == null) {
return null;
}
return getPUDataObject(puFileObject);
}
/**
* Gets the PUDataObject associated with the given <code>project</code>. If there
* was no PUDataObject (i.e. no persistence.xml) in the project, a new one
* will be created and version will be determined based on project classpath. Use
* {@link #getDDFile} for testing whether a project has a persistence.xml file.
* It's not recommended to call this method if there is no PUDataObject yet, it's better o get version first and call with version
*
*@param project the project whose PUDataObject is to be get. Must not be null.
*
*@return <code>PUDataObject</code> associated with the given project or null
* if there is no such <code>PUDataObject</code>.
*
* @throws InvalidPersistenceXmlException if the given <code>project</code> had an existing
* invalid persitence.xml file.
*/
public static synchronized PUDataObject getPUDataObject(Project project) throws InvalidPersistenceXmlException {
return getPUDataObject(project, null);
}
/**
* Creates a new FileObject representing file that defines
* persistence units (<tt>persistence.xml</tt>). <i>Todo: move somewhere else?</i>
* @vers persistence version, if null will be determined from project classpath, if fails default will be 1.0
* @return FileObject representing <tt>persistence.xml</tt>.
*/
private static FileObject createPersistenceDDFile(Project project, FileObject fo, String vers) throws IOException {
final FileObject persistenceLocation = PersistenceLocation.createLocation(project, fo);
if (persistenceLocation == null) {
return null;
}
final FileObject[] dd = new FileObject[1];
//get max supported version
String ret = vers == null ? PersistenceUtils.getJPAVersion(project) : vers;
final String version = ret != null ? ret : Persistence.VERSION_1_0;
// must create the file using AtomicAction, see #72058
persistenceLocation.getFileSystem().runAtomicAction(new FileSystem.AtomicAction() {
public void run() throws IOException {
dd[0] = FileUtil.copyFile(FileUtil.getConfigFile(
"org-netbeans-modules-j2ee-persistence/persistence-" + version + ".xml"), persistenceLocation, "persistence"); //NOI18N
}
});
PersistenceUtils.logUsage(ProviderUtil.class, "USG_PERSISTENCE_XML_CREATED", new String[]{version});
return dd[0];
}
/**
* Checks whether the given project has a persistence.xml that contains at least one
* persistence unit.
*
* @param project the project; must not be null.
*
* @return true if the given project has a persistence.xml containing
* at least one persitence unit, false otherwise.
*
* @throws InvalidPersistenceXmlException if the given <code>project</code> has an
* invalid persistence.xml file.
*/
public static boolean persistenceExists(Project project) throws InvalidPersistenceXmlException {
return persistenceExists(project, null);
}
/**
* Checks whether the given project has a persistence.xml associated with the given FileObject
* that contains at least one persistence unit.
*
* @param project the project; must not be null.
* @param fo the FileObject
*
* @return true if the given project has a persistence.xml associated with the given FileObject
* containing at least one persitence unit, false otherwise.
*
* @throws InvalidPersistenceXmlException if the given <code>project</code> has an
* invalid persistence.xml file.
* @since 1.55
*/
public static boolean persistenceExists(Project project, FileObject fo) throws InvalidPersistenceXmlException {
Parameters.notNull("project", project); //NOI18N
if (getDDFile(project, fo) == null) {
return false;
}
PUDataObject pud = getPUDataObject(project, fo, null);
try {
return pud.getPersistence().getPersistenceUnit().length > 0;
} catch (RuntimeException ex) {
throw new InvalidPersistenceXmlException(ex.getMessage(), null);//persistence.xml may be corrupted and some parsing ways throw runtime
}
}
/**
* @return persistence.xml descriptor of first MetadataUnit found on project or null if none found
*/
public static FileObject getDDFile(Project project) {
return getDDFile(project, null);
}
/**
* @return persistence.xml descriptor of first MetadataUnit associated with the FileObject or null if none found
* @since 1.55
*/
public static FileObject getDDFile(Project project, FileObject fo) {
PersistenceScope[] persistenceScopes = PersistenceUtils.getPersistenceScopes(project, fo);
for (int i = 0; i < persistenceScopes.length; i++) {
return persistenceScopes[i].getPersistenceXml();
}
return null;
}
public static String getDatasourceName(PersistenceUnit pu) {
String datasourceName = pu.getJtaDataSource();
if (datasourceName == null) {
datasourceName = pu.getNonJtaDataSource();
}
return datasourceName;
}
/**
* @return array of providers known to the IDE.
*/
public static Provider[] getAllProviders() {
return new Provider[]{
ECLIPSELINK_PROVIDER, ECLIPSELINK_PROVIDER2_0, ECLIPSELINK_PROVIDER1_0,
TOPLINK_PROVIDER1_0,
HIBERNATE_PROVIDER2_1, HIBERNATE_PROVIDER2_0, HIBERNATE_PROVIDER,
KODO_PROVIDER, DATANUCLEUS_PROVIDER,
OPENJPA_PROVIDER, OPENJPA_PROVIDER1_0, OPENJPA_PROVIDER2_1,
TOPLINK_PROVIDER_55_COMPATIBLE};
}
/**
* Makes the given persistence unit portable if possible, i.e. removes the provider class from it.
* A persistence unit may be made portable if it uses the default provider of the project's target
* server, it doesn't specify any properties and it is not defined in Java SE environment.
*
* @param project the project in which the given persistence unit is defined. Must not be null.
* @param persistenceUnit the persistence unit to be made portable. Must not be null.
*
* @return true if given persistence unit could be made portable, false otherwise.
*
* @throws NullPointerException if either project or persistenceUnit was null.
*/
public static boolean makePortableIfPossible(Project project, PersistenceUnit persistenceUnit) {
return normalizeIfPossible(project, persistenceUnit, true);
}
/**
* Makes the given persistence unit portable if possible, i.e. removes the provider class from it.
* A persistence unit may be made portable if it uses the default provider of the project's target
* server, it doesn't specify any properties and it is not defined in Java SE environment.
* Restore provider class if necessary if there are properties and pu can't be fully portable
*
* @param project the project in which the given persistence unit is defined. Must not be null.
* @param persistenceUnit the persistence unit to be made portable. Must not be null.
*
* @return true if given persistence unit could be made portable, false otherwise.
*
* @throws NullPointerException if either project or persistenceUnit was null.
*/
public static boolean normalizeIfPossible(Project project, PersistenceUnit persistenceUnit) {
return normalizeIfPossible(project, persistenceUnit, false);
}
private static boolean normalizeIfPossible(Project project, PersistenceUnit persistenceUnit, boolean donotrestore) {
Parameters.notNull("project", project); //NOI18N
Parameters.notNull("persistenceUnit", persistenceUnit); //NOI18N
if (Util.isJavaSE(project)) {
return false;
}
Provider defaultProvider = getContainerManagedProvider(project);
if (defaultProvider == null) {
return false;
}
boolean requiredTag = isProviderTagRequired(project);
int notPortablePropSize = persistenceUnit.getProperties() == null ? 0 : persistenceUnit.getProperties().sizeProperty2();
if(persistenceUnit.getProperties() != null) {
for(Property prop:persistenceUnit.getProperties().getProperty2()) {
if(prop.getName().startsWith("javax.persistence.")) {//not vendor specific
notPortablePropSize--;
}
}
}
if((notPortablePropSize == 0) && !requiredTag){
if (defaultProvider.getProviderClass()!=null && defaultProvider.getProviderClass().equals(persistenceUnit.getProvider())) {
persistenceUnit.setProvider(null);
return true;
}
} else if (persistenceUnit.getProvider() == null && (notPortablePropSize > 0 || requiredTag) && !donotrestore){
persistenceUnit.setProvider(defaultProvider.getProviderClass());
}
return false;
}
/**
* Checks whether the given <code>project</code>'s target server is present.
*
* @param project the project whose target server's presence is checked; must not be null.
* @return true if the given <code>project</code> has its target server present or
* if the project does not need a target server (i.e. it is not a J2EE project), false otherwise.
* @throws NullPointerException if the given <code>project</code> was null.
*/
public static boolean isValidServerInstanceOrNone(Project project) {
Parameters.notNull("project", project);
ServerStatusProvider serverStatusProvider = project.getLookup().lookup(ServerStatusProvider.class);
if (serverStatusProvider == null) {
// not a J2EE project
return true;
}
return serverStatusProvider.validServerInstancePresent();
}
public static boolean canServerBeSelected(Project project) {
Parameters.notNull("project", project);
ServerStatusProvider2 serverStatusProvider = project.getLookup().lookup(ServerStatusProvider2.class);
return serverStatusProvider != null;
}
/**
* Help to migrate the Toplink properties to the corresponding Eclipselink ones and vice versa
*
* @param prevProvider the provider class string
* @param curProvider the provider class string
* @param persistenceUnit the persistence unit that is being modified on
*/
public static void migrateProperties(String prevProvider, String curProvider, PersistenceUnit persistenceUnit) {
if (prevProvider.equals("oracle.toplink.essentials.PersistenceProvider") && // NOI18N
curProvider.equals("org.eclipse.persistence.jpa.PersistenceProvider")) { // NOI18N
// Migrate TopLink properties to EclipseLink
Property[] toplinkProps = persistenceUnit.getProperties().getProperty2();
for (int i = 0; i < toplinkProps.length; i++) {
if (toplinkProps[i].getName().contains("toplink")) { // NOI18N
String propName = toplinkProps[i].getName();
propName = propName.replace("toplink", "eclipselink"); // NOI18N
Property eclipselinkProp = persistenceUnit.getProperties().newProperty();
eclipselinkProp.setName(propName);
eclipselinkProp.setValue(toplinkProps[i].getValue());
persistenceUnit.getProperties().removeProperty2(toplinkProps[i]);
persistenceUnit.getProperties().addProperty2(eclipselinkProp);
}
}
} else if (prevProvider.equals("org.eclipse.persistence.jpa.PersistenceProvider") && // NOI18N
curProvider.equals("oracle.toplink.essentials.PersistenceProvider")) { // NOI18N
// Change back to TopLink properties from EclipseLink
Property[] eclipselinkProps = persistenceUnit.getProperties().getProperty2();
for (int i = 0; i < eclipselinkProps.length; i++) {
if (eclipselinkProps[i].getName().contains("eclipselink")) { // NOI18N
String propName = eclipselinkProps[i].getName();
propName = propName.replace("eclipselink", "toplink"); // NOI18N
Property toplinkProp = persistenceUnit.getProperties().newProperty();
toplinkProp.setName(propName);
toplinkProp.setValue(eclipselinkProps[i].getValue());
persistenceUnit.getProperties().removeProperty2(eclipselinkProps[i]);
persistenceUnit.getProperties().addProperty2(toplinkProp);
}
}
}
}
/*
* currently it's workaroud for spring support. spring support rrequires provider class in pu even for jee environment with default provider support
* see issue #195973
* TODO: consider if it should be implemented in some persistence provider (but it's likely will duplicate code for each project)
* TODO: consider if it should be in J2eeProjectCapabilities
*/
private static boolean isProviderTagRequired(Project project){
// check if swdp is already part of classpath
SourceGroup[] sgs = ProjectUtils.getSources(project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
if (sgs.length < 1) {
return false;
}
FileObject sourceRoot = sgs[0].getRootFolder();
ClassPath classPath = ClassPath.getClassPath(sourceRoot, ClassPath.COMPILE);
//this package name will change when open source, should just rely on subclass to use file names
FileObject utxClass = classPath.findResource("org/springframework/transaction/annotation/Transactional.class"); // NOI18N
if (utxClass != null) {
return true;
}
return false;
}
}