| /* |
| * 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.wizard; |
| |
| import java.awt.Component; |
| import java.beans.PropertyChangeEvent; |
| import java.beans.PropertyChangeListener; |
| import javax.swing.JButton; |
| import javax.swing.JLabel; |
| import java.awt.Container; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import javax.swing.JComponent; |
| import java.util.Vector; |
| import java.util.Iterator; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import javax.swing.*; |
| import org.netbeans.api.db.explorer.ConnectionManager; |
| import org.netbeans.api.db.explorer.DatabaseConnection; |
| import org.netbeans.api.db.explorer.JDBCDriver; |
| import org.netbeans.api.db.explorer.JDBCDriverManager; |
| import org.netbeans.api.java.classpath.ClassPath; |
| import org.netbeans.api.java.classpath.JavaClassPathConstants; |
| import org.netbeans.api.java.project.JavaProjectConstants; |
| import org.netbeans.api.java.project.classpath.ProjectClassPathModifier; |
| import org.netbeans.api.progress.ProgressUtils; |
| import org.netbeans.api.project.Project; |
| import org.netbeans.api.project.ProjectUtils; |
| import org.netbeans.api.project.SourceGroup; |
| import org.netbeans.api.project.Sources; |
| import org.netbeans.api.project.libraries.Library; |
| import org.netbeans.api.project.libraries.LibraryManager; |
| import org.netbeans.modules.j2ee.persistence.api.PersistenceScope; |
| import org.netbeans.modules.j2ee.persistence.dd.PersistenceMetadata; |
| 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.provider.DefaultProvider; |
| import org.netbeans.modules.j2ee.persistence.provider.InvalidPersistenceXmlException; |
| import org.netbeans.modules.j2ee.persistence.provider.Provider; |
| import org.netbeans.modules.j2ee.persistence.provider.ProviderUtil; |
| import org.netbeans.modules.j2ee.persistence.spi.datasource.JPADataSourceProvider; |
| import org.netbeans.modules.j2ee.persistence.spi.moduleinfo.JPAModuleInfo; |
| import org.netbeans.modules.j2ee.persistence.spi.provider.PersistenceProviderSupplier; |
| import org.netbeans.modules.j2ee.persistence.unit.PUDataObject; |
| import org.netbeans.modules.j2ee.persistence.wizard.entity.WrapperPanel; |
| import org.netbeans.modules.j2ee.persistence.wizard.fromdb.RelatedCMPWizard; |
| import org.netbeans.modules.j2ee.persistence.wizard.library.PersistenceLibrarySupport; |
| import org.netbeans.modules.j2ee.persistence.wizard.unit.PersistenceUnitWizardPanel.TableGeneration; |
| import org.netbeans.modules.j2ee.persistence.wizard.unit.PersistenceUnitWizardPanel; |
| import org.netbeans.modules.j2ee.persistence.wizard.unit.PersistenceUnitWizardPanelDS; |
| import org.netbeans.modules.j2ee.persistence.wizard.unit.PersistenceUnitWizardPanelJdbc; |
| import org.netbeans.spi.java.classpath.support.ClassPathSupport; |
| import org.openide.DialogDescriptor; |
| import org.openide.DialogDisplayer; |
| import org.openide.filesystems.FileObject; |
| import org.openide.util.NbBundle; |
| |
| /** |
| * Copy of j2ee/utilities Util class |
| */ |
| public class Util { |
| |
| private static final String[] JPA_VERSIONS = {Persistence.VERSION_1_0, Persistence.VERSION_2_0, Persistence.VERSION_2_1}; |
| |
| /* |
| * Changes the text of a JLabel in component from oldLabel to newLabel |
| */ |
| public static void changeLabelInComponent(JComponent component, String oldLabel, String newLabel) { |
| JLabel label = findLabel(component, oldLabel); |
| if (label != null) { |
| label.setText(newLabel); |
| } |
| } |
| |
| /* |
| * Hides a JLabel and the component that it is designated to labelFor, if any |
| */ |
| public static void hideLabelAndLabelFor(JComponent component, String lab) { |
| JLabel label = findLabel(component, lab); |
| if (label != null) { |
| label.setVisible(false); |
| Component c = label.getLabelFor(); |
| if (c != null) { |
| c.setVisible(false); |
| } |
| } |
| } |
| |
| /* |
| * Recursively gets all components in the components array and puts it in allComponents |
| */ |
| public static void getAllComponents(Component[] components, Collection allComponents) { |
| for (int i = 0; i < components.length; i++) { |
| if (components[i] != null) { |
| allComponents.add(components[i]); |
| if (((Container) components[i]).getComponentCount() != 0) { |
| getAllComponents(((Container) components[i]).getComponents(), allComponents); |
| } |
| } |
| } |
| } |
| |
| /* |
| * Recursively finds a JLabel that has labelText in comp |
| */ |
| public static JLabel findLabel(JComponent comp, String labelText) { |
| Vector allComponents = new Vector(); |
| getAllComponents(comp.getComponents(), allComponents); |
| Iterator iterator = allComponents.iterator(); |
| while (iterator.hasNext()) { |
| Component c = (Component) iterator.next(); |
| if (c instanceof JLabel) { |
| JLabel label = (JLabel) c; |
| if (label.getText().equals(labelText)) { |
| return label; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the SourceGroup of the passesd project which contains the |
| * fully-qualified class name. |
| */ |
| public static SourceGroup getClassSourceGroup(Project project, String fqClassName) { |
| String classFile = fqClassName.replace('.', '/') + ".java"; // NOI18N |
| SourceGroup[] sourceGroups = ProjectUtils.getSources(project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA); |
| |
| for (SourceGroup sourceGroup : sourceGroups) { |
| FileObject classFO = sourceGroup.getRootFolder().getFileObject(classFile); |
| if (classFO != null) { |
| return sourceGroup; |
| } |
| } |
| return null; |
| } |
| |
| public static ClassPath getFullClasspath(FileObject fo) { |
| FileObject[] sourceRoots = ClassPath.getClassPath(fo, ClassPath.SOURCE).getRoots(); |
| FileObject[] bootRoots = ClassPath.getClassPath(fo, ClassPath.BOOT).getRoots(); |
| FileObject[] compileRoots = ClassPath.getClassPath(fo, ClassPath.COMPILE).getRoots(); |
| FileObject[] roots = new FileObject[sourceRoots.length + bootRoots.length + compileRoots.length]; |
| System.arraycopy(sourceRoots, 0, roots, 0, sourceRoots.length); |
| System.arraycopy(bootRoots, 0, roots, sourceRoots.length, bootRoots.length); |
| System.arraycopy(compileRoots, 0, roots, sourceRoots.length + bootRoots.length, compileRoots.length); |
| return ClassPathSupport.createClassPath(roots); |
| } |
| |
| // from ejbcore utils |
| public static boolean isSupportedJavaEEVersion(Project project) { |
| JPAModuleInfo moduleInfo = project.getLookup().lookup(JPAModuleInfo.class); |
| if (moduleInfo == null) { |
| return false; |
| } |
| if (JPAModuleInfo.ModuleType.EJB == moduleInfo.getType() |
| && ("3.1".equals(moduleInfo.getVersion()) || "3.0".equals(moduleInfo.getVersion()) || "3.2".equals(moduleInfo.getVersion()))) { |
| return true; |
| } |
| if (JPAModuleInfo.ModuleType.WEB == moduleInfo.getType() |
| && ("3.1".equals(moduleInfo.getVersion()) || "3.0".equals(moduleInfo.getVersion()) || "2.5".equals(moduleInfo.getVersion()))) { |
| return true; |
| } |
| return false; |
| } |
| |
| public static boolean isContainerManaged(Project project) { |
| PersistenceProviderSupplier providerSupplier = project.getLookup().lookup(PersistenceProviderSupplier.class); |
| return Util.isSupportedJavaEEVersion(project) && providerSupplier != null && providerSupplier.supportsDefaultProvider(); |
| } |
| |
| public static Provider getDefaultProvider(Project project) { |
| PersistenceProviderSupplier providerSupplier = project.getLookup().lookup(PersistenceProviderSupplier.class); |
| if ((providerSupplier != null && providerSupplier.supportsDefaultProvider())) { |
| List<Provider> providers = providerSupplier.getSupportedProviders(); |
| if (providers.size() > 0) { |
| return providers.get(0); |
| } |
| Logger.getLogger(RelatedCMPWizard.class.getName()).log(Level.WARNING, "Default provider support is reported without any supported providers. See: {0}", providerSupplier); |
| } |
| return null; |
| } |
| |
| public static ArrayList<Provider> getProviders(Project project) { |
| PersistenceProviderSupplier aProviderSupplier = project.getLookup().lookup(PersistenceProviderSupplier.class); |
| |
| if (aProviderSupplier == null) { |
| // a java se project |
| aProviderSupplier = new DefaultPersistenceProviderSupplier(); |
| } |
| |
| ArrayList<Provider> providers = new ArrayList<Provider>(aProviderSupplier.getSupportedProviders()); |
| if (providers.isEmpty() && aProviderSupplier.supportsDefaultProvider()) { |
| providers.add(ProviderUtil.DEFAULT_PROVIDER); |
| } |
| // |
| return providers; |
| } |
| |
| /** |
| * check all available providers and return default/first/or ECLIPSELINK if prefereed |
| * @param project |
| * @return |
| */ |
| public static Provider getPreferredProvider(Project project){ |
| //choose default/first provider |
| ArrayList<Provider> providers = getProviders(project); |
| int defIndex = 0; |
| if(providers.size()>1){//if it's possible to select preferred jpa2.0 provider, we'll select instead of jpa1.0 default one |
| String defProviderVersion = ProviderUtil.getVersion((Provider) providers.get(0)); |
| boolean specialCase = (Util.isJPAVersionSupported(project, Persistence.VERSION_2_0) || Util.isJPAVersionSupported(project, Persistence.VERSION_2_1)) && (defProviderVersion == null || defProviderVersion.equals(Persistence.VERSION_1_0));//jpa 2.0 is supported by default (or first) is jpa1.0 or udefined version provider |
| if(specialCase){ |
| for (int i = 1; i<providers.size() ; i++){ |
| if(ProviderUtil.ECLIPSELINK_PROVIDER.equals(providers.get(i))){//eclipselink jpa2.1 is preferred provider |
| defIndex = i; |
| break; |
| } |
| } |
| } |
| } |
| if(providers.isEmpty()) { |
| Logger.getLogger(RelatedCMPWizard.class.getName()).log(Level.INFO, "Can't find any providers supported by the project: {0}", project); //NOI18N |
| } |
| return providers.size()>0 ? providers.get(defIndex) : null; |
| } |
| |
| public static boolean isDefaultProvider(Project project, Provider provider) { |
| return provider != null && provider.equals(getDefaultProvider(project)); |
| } |
| |
| public static boolean isEjbModule(Project project) { |
| JPAModuleInfo moduleInfo = project.getLookup().lookup(JPAModuleInfo.class); |
| if (moduleInfo == null) { |
| return false; |
| } |
| return JPAModuleInfo.ModuleType.EJB == moduleInfo.getType(); |
| } |
| |
| public static boolean isEjb21Module(Project project) { |
| JPAModuleInfo moduleInfo = project.getLookup().lookup(JPAModuleInfo.class); |
| if (moduleInfo == null) { |
| return false; |
| } |
| |
| return JPAModuleInfo.ModuleType.EJB == moduleInfo.getType() |
| && "2.1".equals(moduleInfo.getVersion()); |
| } |
| |
| /** |
| * @return true if given this data object's project's enviroment is Java SE, false otherwise. |
| */ |
| public static boolean isJavaSE(Project project) { |
| return project.getLookup().lookup(JPAModuleInfo.class) == null; |
| } |
| |
| /** |
| * Builds a persistence unit using wizard. Does not save the created persistence unit |
| * nor create the persistence.xml file if it does not exist. |
| * @param project the current project |
| * @param preselectedDB the name of the database connection that should be preselected in the wizard. |
| * @tableGeneration the table generation strategy that should be preselected in the wizard. |
| * @return the created PersistenceUnit or null if nothing was created, for example |
| * if wizard was cancelled. |
| */ |
| public static PersistenceUnit buildPersistenceUnitUsingWizard(Project project, |
| String preselectedDB, TableGeneration tableGeneration) { |
| |
| boolean isContainerManaged = Util.isContainerManaged(project); |
| PersistenceUnitWizardPanel panel; |
| if (isContainerManaged) { |
| panel = new PersistenceUnitWizardPanelDS(project, null, true, tableGeneration); |
| } else { |
| panel = new PersistenceUnitWizardPanelJdbc(project, null, true, tableGeneration); |
| } |
| if (preselectedDB != null) { |
| panel.setPreselectedDB(preselectedDB); |
| } |
| |
| final JButton createPUButton = new JButton(NbBundle.getMessage(Util.class, "LBL_CreatePersistenceUnitButton")); |
| createPUButton.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(Util.class, "ACSD_CreatePersistenceUnitButton")); |
| Object[] buttons = new Object[]{createPUButton, DialogDescriptor.CANCEL_OPTION}; |
| |
| final DialogDescriptor nd = new DialogDescriptor( |
| new WrapperPanel(panel), |
| NbBundle.getMessage(Util.class, "LBL_CreatePersistenceUnit").replace("&", ""),//NOI18N |
| true, |
| buttons, |
| DialogDescriptor.OK_OPTION, |
| DialogDescriptor.DEFAULT_ALIGN, |
| null, |
| null); |
| panel.addPropertyChangeListener(new PropertyChangeListener() { |
| |
| @Override |
| public void propertyChange(PropertyChangeEvent evt) { |
| if (evt.getPropertyName().equals(PersistenceUnitWizardPanel.IS_VALID)) { |
| Object newvalue = evt.getNewValue(); |
| if ((newvalue != null) && (newvalue instanceof Boolean)) { |
| nd.setValid(((Boolean) newvalue).booleanValue()); |
| createPUButton.setEnabled(((Boolean) newvalue).booleanValue()); |
| } |
| } |
| } |
| }); |
| if (!panel.isValidPanel()) { |
| nd.setValid(false); |
| createPUButton.setEnabled(false); |
| } |
| Object result = DialogDisplayer.getDefault().notify(nd); |
| //add necessary libraries before pu creation |
| Library lib = null; |
| boolean libIsAdded = false;//used to check if lib was added to compile classpath |
| if (result == createPUButton) { |
| if (isContainerManaged) { |
| //TODO: verify if need to add library here |
| PersistenceUnitWizardPanelDS puDS = (PersistenceUnitWizardPanelDS) panel; |
| lib = PersistenceLibrarySupport.getLibrary(puDS.getSelectedProvider()); |
| } else { |
| PersistenceUnitWizardPanelJdbc puJdbc = (PersistenceUnitWizardPanelJdbc) panel; |
| lib = PersistenceLibrarySupport.getLibrary(puJdbc.getSelectedProvider()); |
| //TODO: verify if don't need to add library here |
| if (lib != null) { |
| libIsAdded = true; |
| addLibraryToProject(project, lib); |
| } |
| JDBCDriver[] driver = JDBCDriverManager.getDefault().getDrivers(puJdbc.getPersistenceConnection().getDriverClass()); |
| PersistenceLibrarySupport.addDriver(project, driver[0]); |
| } |
| } |
| String version = (lib != null && libIsAdded) ? PersistenceUtils.getJPAVersion(lib) : PersistenceUtils.getJPAVersion(project);//use library if possible it will provide better result, TODO: may be usage of project should be removed and use 1.0 is no library was found |
| if (result == createPUButton) { |
| PersistenceUnit punit = null; |
| if (Persistence.VERSION_2_1.equals(version)) { |
| punit = new org.netbeans.modules.j2ee.persistence.dd.persistence.model_2_1.PersistenceUnit(); |
| } else if (Persistence.VERSION_2_0.equals(version)) { |
| punit = new org.netbeans.modules.j2ee.persistence.dd.persistence.model_2_0.PersistenceUnit(); |
| } else {//currently default 1.0 |
| punit = new org.netbeans.modules.j2ee.persistence.dd.persistence.model_1_0.PersistenceUnit(); |
| } |
| if (isContainerManaged) { |
| PersistenceUnitWizardPanelDS puPanel = (PersistenceUnitWizardPanelDS) panel; |
| if (puPanel.getDatasource() != null && !"".equals(puPanel.getDatasource().trim())) { |
| if (puPanel.isJTA()) { |
| punit.setJtaDataSource(puPanel.getDatasource()); |
| } else { |
| if (puPanel.isNonDefaultProviderEnabled()) { |
| punit.setNonJtaDataSource(puPanel.getDatasource()); |
| } |
| punit.setTransactionType("RESOURCE_LOCAL"); |
| } |
| } |
| if (puPanel.isNonDefaultProviderEnabled()) { |
| punit.setProvider(puPanel.getNonDefaultProvider()); |
| } |
| } else { |
| PersistenceUnitWizardPanelJdbc puJdbc = (PersistenceUnitWizardPanelJdbc) panel; |
| punit = ProviderUtil.buildPersistenceUnit(puJdbc.getPersistenceUnitName(), puJdbc.getSelectedProvider(), puJdbc.getPersistenceConnection(), version); |
| punit.setTransactionType("RESOURCE_LOCAL"); //NOI18N |
| // Explicitly add <exclude-unlisted-classes>false</exclude-unlisted-classes> |
| // See issue 142575 - desc 10 |
| if (!Util.isJavaSE(project)) { |
| punit.setExcludeUnlistedClasses(false); |
| } |
| } |
| punit.setName(panel.getPersistenceUnitName()); |
| ProviderUtil.setTableGeneration(punit, panel.getTableGeneration(), project); |
| return punit; |
| } |
| return null; |
| |
| } |
| |
| /** |
| * Builds a persistence unit using data passed as parameters. Does not save the created persistence unit |
| * nor create the persistence.xml file if it does not exist. |
| * If some parameters are null, try to find default one or best match |
| * @param project the current project |
| * @param name name for pu, if null default will be used |
| * @param preselectedDB the name of the database connection that should be preselected in the wizard. |
| * @tableGeneration the table generation strategy that should be preselected in the wizard. |
| * @return the created PersistenceUnit or null if nothing was created, for example |
| * if wizard was cancelled. |
| */ |
| public static PersistenceUnit buildPersistenceUnitUsingData(Project project, String puName, |
| String preselectedDB, TableGeneration tableGeneration, Provider provider) { |
| return buildPersistenceUnitUsingData(project, puName, preselectedDB, tableGeneration, provider, null); |
| } |
| /** |
| * Builds a persistence unit using data passed as parameters. Does not save the created persistence unit |
| * nor create the persistence.xml file if it does not exist. |
| * If some parameters are null, try to find default one or best match |
| * @param project the current project |
| * @param name name for pu, if null default will be used |
| * @param preselectedDB the name of the database connection that should be preselected in the wizard. |
| * @tableGeneration the table generation strategy that should be preselected in the wizard. |
| * @param puVersion pu will be created with passed as a parameter jpa version but will be limited by project/provider properties (can't create 2.0 in project and provider with 1.0 support only). |
| * @return the created PersistenceUnit or null if nothing was created, for example |
| * if wizard was cancelled. |
| */ |
| public static PersistenceUnit buildPersistenceUnitUsingData(Project project, String puName, |
| String preselectedDB, TableGeneration tableGeneration, Provider provider, String puVersion) { |
| |
| boolean isContainerManaged = Util.isContainerManaged(project); |
| |
| if (provider == null) { |
| //choose default/first provider |
| provider = getPreferredProvider(project); |
| } |
| if (provider == null) { |
| //sometimes project may not report any provider as supported, use eclipselink as a base |
| provider = ProviderUtil.ECLIPSELINK_PROVIDER; |
| } |
| //add necessary libraries before pu creation |
| Library lib = null; |
| boolean libIsAdded = false;//used to check if lib was added to compile classpath |
| if (isContainerManaged) { |
| //TODO: verify if need to add library here |
| lib = PersistenceLibrarySupport.getLibrary(provider); |
| } else { |
| lib = PersistenceLibrarySupport.getLibrary(provider); |
| //TODO: verify if don't need to add library here |
| if (lib != null) { |
| addLibraryToProject(project, lib); |
| libIsAdded = true; |
| } |
| } |
| |
| String version = (lib != null && libIsAdded) ? PersistenceUtils.getJPAVersion(lib) : PersistenceUtils.getJPAVersion(project);//use library if possible it will provide better result, TODO: may be usage of project should be removed and use 1.0 is no library was found |
| if (provider != null && version != null) { |
| String provVersion = ProviderUtil.getVersion(provider); |
| if (provVersion != null) { |
| //even if project support jpa 2.0 etc, but selected provider is reported as jpa1.0 use jpa1.0 |
| if (Double.parseDouble(version) > Double.parseDouble(provVersion)) { |
| version = provVersion; |
| } |
| } |
| } |
| if(puVersion != null){ |
| if (Double.parseDouble(version) > Double.parseDouble(puVersion)) { |
| version = puVersion;//if passed version less then supported we can use lower version. |
| } |
| } |
| PersistenceUnit punit = null; |
| if (Persistence.VERSION_2_1.equals(version)) { |
| punit = new org.netbeans.modules.j2ee.persistence.dd.persistence.model_2_1.PersistenceUnit(); |
| } else if (Persistence.VERSION_2_0.equals(version)) { |
| punit = new org.netbeans.modules.j2ee.persistence.dd.persistence.model_2_0.PersistenceUnit(); |
| } else {//currently default 1.0 |
| punit = new org.netbeans.modules.j2ee.persistence.dd.persistence.model_1_0.PersistenceUnit(); |
| } |
| if (isContainerManaged) { |
| if (preselectedDB == null || preselectedDB.trim().equals("")) { |
| //find first with default/sample part in name |
| JPADataSourceProvider dsProvider = project.getLookup().lookup(JPADataSourceProvider.class); |
| if (dsProvider.getDataSources().size() > 0) { |
| preselectedDB = dsProvider.getDataSources().get(0).getDisplayName(); |
| } |
| } |
| if (preselectedDB != null && !"".equals(preselectedDB.trim())) { |
| punit.setJtaDataSource(preselectedDB); |
| } |
| if (!(provider instanceof DefaultProvider)) { |
| punit.setProvider(provider.getProviderClass()); |
| } |
| // Explicitly add <exclude-unlisted-classes>false</exclude-unlisted-classes> |
| // See issue 142575 - desc 10 |
| // also it shouldn't change default behavior as default for containers should be the same |
| punit.setExcludeUnlistedClasses(false); |
| } else { |
| DatabaseConnection connection = null; |
| if (preselectedDB != null && !preselectedDB.trim().equals("")) { |
| connection = ConnectionManager.getDefault().getConnection(preselectedDB); |
| } |
| if (connection == null) { |
| ConnectionManager cm = ConnectionManager.getDefault(); |
| DatabaseConnection[] connections = cm.getConnections(); |
| connection = connections != null && connections.length > 0 ? connections[0] : null; |
| } |
| punit = ProviderUtil.buildPersistenceUnit("tmp", provider, connection, version); |
| punit.setTransactionType("RESOURCE_LOCAL"); //NOI18N |
| // Explicitly add <exclude-unlisted-classes>false</exclude-unlisted-classes> |
| // See issue 142575 - desc 10, and issue 180810 |
| if (!Util.isJavaSE(project)) { |
| punit.setExcludeUnlistedClasses(false); |
| } |
| } |
| if (puName == null) { |
| puName = getCandidateName(project); |
| } |
| punit.setName(puName); |
| ProviderUtil.setTableGeneration(punit, tableGeneration != null ? tableGeneration.name() : TableGeneration.NONE.name(), project); |
| return punit; |
| } |
| |
| /** |
| * |
| * @return true if jpa version is supported by platform (may need to be extended to classpath check and possible library addition check but not in this method |
| * it's used to check server support in current realization) |
| */ |
| public static boolean isJPAVersionSupported(Project project, String version){ |
| JPAModuleInfo info = project.getLookup().lookup(JPAModuleInfo.class); |
| if(info!=null){ |
| return !Boolean.FALSE.equals(info.isJPAVersionSupported(version));//null return considerd valid too and the same as true |
| } |
| return true; |
| |
| } |
| |
| /** |
| * return jpa version supported in the project and no more then top bound |
| * @param top - upper bound for jpa version to return |
| * @return return top most supported version less or equal to 'top' |
| */ |
| public static String getJPAVersionSupported(Project project, String top){ |
| JPAModuleInfo info = project.getLookup().lookup(JPAModuleInfo.class); |
| boolean top_found = false; |
| if(info!=null){ |
| for(int i=JPA_VERSIONS.length-1;i>=0;i--){ |
| if(JPA_VERSIONS[i].equals(top)){ |
| top_found = true; |
| } |
| if(top_found){ |
| if(!Boolean.FALSE.equals(info.isJPAVersionSupported(JPA_VERSIONS[i]))){ |
| return JPA_VERSIONS[i]; |
| }//null return considerd valid too and the same as true |
| } |
| } |
| } |
| return JPA_VERSIONS[0];//can't verify and return lowest |
| } |
| |
| /** |
| * Creates a persistence unit using the PU wizard and adds the created |
| * persistence unit to the given project's <code>PUDataObject</code> and saves it. |
| * |
| * @param project the project to which the created persistence unit is to be created. |
| * @param preselectedDB the name of the db connection that should be preselected, or null if none needs |
| * to be preselected. |
| * @param tableGeneration the table generation strategy for the persistence unit. |
| * |
| * @return true if the creation of the persistence unit was successful, false otherwise. |
| * |
| * @throws InvalidPersistenceXmlException if the persistence.xml file in the given |
| * project is not valid. |
| * |
| */ |
| public static boolean createPersistenceUnitUsingWizard(Project project, |
| String preselectedDB, TableGeneration tableGeneration) throws InvalidPersistenceXmlException { |
| |
| PersistenceUnit punit = buildPersistenceUnitUsingWizard(project, preselectedDB, tableGeneration); |
| if (punit == null) { |
| return false; |
| } |
| String version = Persistence.VERSION_1_0; |
| if(punit instanceof org.netbeans.modules.j2ee.persistence.dd.persistence.model_2_1.PersistenceUnit) { |
| version = Persistence.VERSION_2_1; |
| } else if(punit instanceof org.netbeans.modules.j2ee.persistence.dd.persistence.model_2_0.PersistenceUnit) { |
| version = Persistence.VERSION_2_0; |
| } |
| PUDataObject pud = ProviderUtil.getPUDataObject(project, version); |
| if (pud == null) { |
| return false; |
| } |
| pud.addPersistenceUnit(punit); |
| pud.save(); |
| return true; |
| } |
| |
| /** |
| * add pu to the project, add persistence libraries if appropriate and known |
| * add db libraries for connection if it's not conteiner managed project |
| * @param project |
| * @param pu |
| */ |
| public static void addPersistenceUnitToProject(Project project, PersistenceUnit persistenceUnit) { |
| addPersistenceUnitToProjectRoot(project, null, persistenceUnit); |
| } |
| |
| /** |
| * add pu to the project's root, add persistence libraries if appropriate and known |
| * add db libraries for connection if it's not conteiner managed project |
| * @param project |
| * @param root |
| * @param pu |
| * @since 1.55 |
| */ |
| public static void addPersistenceUnitToProjectRoot(Project project, FileObject root, PersistenceUnit persistenceUnit) { |
| String providerClass = persistenceUnit.getProvider(); |
| boolean libAdded = false; |
| Library lib = null; |
| if (providerClass != null) { |
| Provider selectedProvider = ProviderUtil.getProvider(providerClass, project); |
| lib = PersistenceLibrarySupport.getLibrary(selectedProvider); |
| if (lib != null) { |
| if (!Util.isDefaultProvider(project, selectedProvider)) { |
| Util.addLibraryToProject(project, lib); |
| libAdded = true; |
| } else if (selectedProvider.getAnnotationProcessor() != null) { |
| Util.addLibraryToProject(project, lib, JavaClassPathConstants.PROCESSOR_PATH); |
| libAdded = true; |
| } |
| } |
| if (!isContainerManaged(project)) { |
| DatabaseConnection connection = ProviderUtil.getConnection(persistenceUnit); |
| if (connection != null) { |
| JDBCDriver[] driver = JDBCDriverManager.getDefault().getDrivers(connection.getDriverClass()); |
| PersistenceLibrarySupport.addDriver(project, driver[0]); |
| } else { |
| Logger.getLogger("global").log(Level.INFO, "Can't find connection for persistence unit"); //NOI18N |
| } |
| } |
| } |
| |
| try { |
| ProviderUtil.addPersistenceUnit(persistenceUnit, project, root); |
| } catch (InvalidPersistenceXmlException ipx) { |
| // just log for debugging purposes, at this point the user has |
| // already been warned about an invalid persistence.xml |
| Logger.getLogger(RelatedCMPWizard.class.getName()).log(Level.FINE, "Invalid persistence.xml: " + ipx.getPath(), ipx); //NOI18N |
| } |
| //need to add ap registration lib if exist |
| if (libAdded && lib != null) { |
| String projVersion = PersistenceUtils.getJPAVersion(project); |
| if( projVersion == null ) { |
| projVersion = "1.0"; |
| }//NOI18N minimum version, will not affect |
| double version = Math.max(Double.parseDouble(PersistenceUtils.getJPAVersion(lib)), Double.parseDouble(projVersion)); |
| if (version > 1.0 && Util.isJPAVersionSupported(project, Double.toString(version))) { |
| Library mLib = LibraryManager.getDefault().getLibrary(lib.getName()+"modelgen");//NOI18N |
| if(mLib!=null) { |
| Util.addLibraryToProject(project, mLib, JavaClassPathConstants.PROCESSOR_PATH); |
| }//no real need to add modelgen to compile classpath |
| } |
| } |
| } |
| |
| /** |
| * Creates a persistence unit with the default table generation strategy using the PU wizard and adds the created |
| * persistence unit to the given project's <code>PUDataObject</code> and saves it. |
| * |
| * @param project the project to which the created persistence unit is to be created. |
| * @param preselectedDB the name of the db connection that should be preselected, or null if none needs |
| * to be preselected. |
| * |
| * @return true if the creation of the persistence unit was successful, false otherwise. |
| * |
| * @throws InvalidPersistenceXmlException if the persistence.xml file in the given |
| * project is not valid. |
| * |
| */ |
| public static boolean createPersistenceUnitUsingWizard(Project project, String preselectedDB) throws InvalidPersistenceXmlException { |
| return createPersistenceUnitUsingWizard(project, preselectedDB, TableGeneration.CREATE); |
| } |
| |
| /** |
| * Ad library to the project to compile classpath(default) |
| * Method is called off of AWT thread |
| * @param project |
| * @param library |
| */ |
| public static void addLibraryToProject(Project project, Library library) { |
| addLibraryToProject(project, library, ClassPath.COMPILE); |
| } |
| |
| /** |
| * add library to the project to specified classpath |
| * Method is called off of AWT thread |
| * @param project |
| * @param library |
| * @param classpathType |
| */ |
| public static void addLibraryToProject(Project project, Library library, String classpathType) { |
| if(SwingUtilities.isEventDispatchThread()){ |
| AtomicBoolean cancel = new AtomicBoolean(); |
| ProgressUtils.runOffEventDispatchThread( new AddLibrary(project, library, classpathType), |
| NbBundle.getMessage(Util.class, |
| "TTL_ExtendProjectClasspath"), cancel, false ); // NOI18N |
| } else { |
| addLibraryToProject0(project, library, classpathType); |
| } |
| } |
| |
| /** |
| * add persistence api, will be added if no api is present on classpath |
| * @param project |
| */ |
| public static void addPersistenceUnitToProject(Project project) { |
| if(PersistenceUtils.getJPAVersion(project) == null){ |
| Library lib; |
| if(isJPAVersionSupported(project, Persistence.VERSION_2_1) || isJPAVersionSupported(project, Persistence.VERSION_2_0)) { |
| lib = LibraryManager.getDefault().getLibrary("jpa20-persistence"); |
| |
| } else { |
| lib = LibraryManager.getDefault().getLibrary("persistence"); |
| |
| } |
| if(lib != null){ |
| addLibraryToProject(project, lib); |
| } |
| } |
| } |
| |
| private static class AddLibrary implements Runnable{ |
| Project project; |
| Library library; |
| String classpathType; |
| public AddLibrary(Project project, Library library, String classpathType){ |
| this.project = project; |
| this.library = library; |
| this.classpathType = classpathType; |
| } |
| |
| @Override |
| public void run() { |
| addLibraryToProject0(project, library, classpathType); |
| } |
| } |
| |
| private static void addLibraryToProject0(Project project, Library library, String classpathType) { |
| Sources sources = ProjectUtils.getSources(project); |
| SourceGroup groups[] = sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA); |
| SourceGroup firstGroup = groups[0]; |
| FileObject fo = firstGroup.getRootFolder(); |
| try { |
| ProjectClassPathModifier.addLibraries(new Library[]{library}, fo, classpathType); |
| } catch (IOException ex) { |
| Logger.getLogger("global").log(Level.FINE, "Can't add library to the project", ex); |
| } catch (UnsupportedOperationException ex) { |
| Logger.getLogger("global").log(Level.FINE, "Can't add library to the project", ex); |
| } |
| } |
| |
| /** |
| *@return an initial name for a persistence unit, i.e. a name that |
| * is unique. |
| */ |
| public static String getCandidateName(Project project) { |
| String candidateNameBase = ProjectUtils.getInformation(project).getName() + "PU"; //NOI18N |
| try { |
| if (!ProviderUtil.persistenceExists(project)) { |
| return candidateNameBase; |
| } |
| PUDataObject pudo = ProviderUtil.getPUDataObject(project); |
| Persistence persistence = pudo.getPersistence(); |
| |
| int suffix = 2; |
| PersistenceUnit[] punits = persistence.getPersistenceUnit(); |
| String candidateName = candidateNameBase; |
| while (!isUnique(candidateName, punits)) { |
| candidateName = candidateNameBase + suffix++; |
| } |
| return candidateName; |
| } catch (InvalidPersistenceXmlException ipex) { |
| // just log, the user is notified about invalid persistence.xml when |
| // the panel is validated |
| Logger.getLogger("global").log(Level.FINE, "Invalid persistence.xml found", ipex); //NOI18N |
| } |
| return candidateNameBase; |
| } |
| |
| /** |
| * @return true if the given <code>candidate</code> represents a unique |
| * name within the names of the given <code>punits</code>, false otherwise. |
| */ |
| static private boolean isUnique(String candidate, PersistenceUnit[] punits) { |
| for (PersistenceUnit punit : punits) { |
| if (candidate.equals(punit.getName())) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * An implementation of the PersistenceProviderSupplier that returns an list of providers |
| * provided by bundled/registered libraries |
| * and doesn't support a default provider. Used when an implementation of |
| * the PersistenceProviderSupplier can't be found in the project lookup (as is the case |
| * for instance for Java SE projects). |
| */ |
| private static class DefaultPersistenceProviderSupplier implements PersistenceProviderSupplier { |
| |
| @Override |
| public List<Provider> getSupportedProviders() { |
| List<Provider> model = new ArrayList<Provider>(); |
| //get all, but remove duplicates |
| for (Provider each : PersistenceLibrarySupport.getProvidersFromLibraries()) { |
| boolean found = false; |
| for (int i = 0; i < model.size(); i++) { |
| Object elem = model.get(i); |
| if (elem instanceof Provider && each.equals(elem)) { |
| found = true; |
| break; |
| } |
| } |
| if (!found) { |
| model.add(each); |
| } |
| } |
| return model; |
| } |
| |
| @Override |
| public boolean supportsDefaultProvider() { |
| return false; |
| } |
| } |
| |
| public static String getPersistenceUnitAsString(Project project, String entity) throws IOException { |
| String persistenceUnit = null; |
| PersistenceScope persistenceScopes[] = PersistenceUtils.getPersistenceScopes(project); |
| if (persistenceScopes.length > 0) { |
| FileObject persXml = persistenceScopes[0].getPersistenceXml(); |
| if (persXml != null) { |
| Persistence persistence = PersistenceMetadata.getDefault().getRoot(persXml); |
| PersistenceUnit units[] = persistence.getPersistenceUnit(); |
| if (units.length > 0) { |
| persistenceUnit = units[0].getName(); |
| if (units.length > 1) {//find best |
| String forAll = null; |
| String forOne = null; |
| for (int i = 0; i < units.length && forOne == null; i++) { |
| PersistenceUnit tmp = units[i]; |
| if (forAll == null && !tmp.isExcludeUnlistedClasses()) { |
| forAll = tmp.getName();//first match sutable for all entities in the project |
| } |
| if (tmp.isExcludeUnlistedClasses()) { |
| String[] classes = tmp.getClass2(); |
| for (String clas : classes) { |
| if (entity.equals(clas)) { |
| forOne = tmp.getName(); |
| break; |
| } |
| } |
| } |
| } |
| //try again with less restrictions (i.e. for j2se even without exclude-unlisted-classes node, it's by default true) |
| if (forOne == null && forAll != null) {//there is exist pu without exclude-unlisted-classes |
| for (int i = 0; i < units.length && forOne == null; i++) { |
| PersistenceUnit tmp = units[i]; |
| if (!tmp.isExcludeUnlistedClasses()) {//verify only pu without exclude-unlisted-classes as all other was examined in previos try |
| String[] classes = tmp.getClass2(); |
| for (String clas : classes) { |
| if (entity.equals(clas)) { |
| forOne = tmp.getName(); |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| persistenceUnit = forOne != null ? forOne : (forAll != null ? forAll : persistenceUnit); |
| } |
| } |
| } |
| } |
| return persistenceUnit; |
| } |
| public static PersistenceUnit[] getPersistenceUnits(Project project) throws IOException { |
| PersistenceScope persistenceScopes[] = PersistenceUtils.getPersistenceScopes(project); |
| if (persistenceScopes.length > 0) { |
| FileObject persXml = persistenceScopes[0].getPersistenceXml(); |
| if (persXml != null) { |
| Persistence persistence = PersistenceMetadata.getDefault().getRoot(persXml); |
| return persistence.getPersistenceUnit(); |
| } |
| } |
| return new PersistenceUnit[]{}; |
| } |
| |
| //UI support |
| public static Set getSelectedItems(JList list, boolean enabledOnly) { |
| Set result = new HashSet(); |
| |
| int[] selected = list.getSelectedIndices(); |
| for (int i = 0; i < selected.length; i++) { |
| Object item = list.getModel().getElementAt(selected[i]); |
| if (enabledOnly) { |
| if (!list.getCellRenderer().getListCellRendererComponent(list, item, selected[i], false, false).isEnabled()) { |
| continue; |
| } |
| } |
| result.add(item); |
| } |
| |
| return result; |
| } |
| |
| public static Set getEnabledItems(JList list) { |
| Set result = new HashSet(); |
| for (int i = 0; i < list.getModel().getSize(); i++) { |
| Object item = list.getModel().getElementAt(i); |
| if (!list.getCellRenderer().getListCellRendererComponent(list, item, i, false, false).isEnabled()) { |
| continue; |
| } |
| result.add(item); |
| } |
| |
| return result; |
| } |
| } |