| /* |
| * 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; |
| } |
| } |