2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
package org.netbeans.modules.j2ee.persistence.wizard;
44
import java.awt.Component;
45
import java.beans.PropertyChangeEvent;
46
import java.beans.PropertyChangeListener;
47
import javax.swing.JButton;
48
import javax.swing.JLabel;
49
import java.awt.Container;
50
import java.io.IOException;
52
import java.util.ArrayList;
53
import javax.swing.JComponent;
54
import java.util.Vector;
55
import java.util.Iterator;
56
import java.util.Collection;
57
import java.util.Collections;
58
import java.util.HashMap;
59
import java.util.HashSet;
60
import java.util.List;
63
import java.util.logging.Level;
64
import java.util.logging.Logger;
65
import org.netbeans.api.java.classpath.ClassPath;
66
import org.netbeans.api.java.project.JavaProjectConstants;
67
import org.netbeans.api.java.queries.UnitTestForSourceQuery;
68
import org.netbeans.api.project.Project;
69
import org.netbeans.api.project.ProjectUtils;
70
import org.netbeans.api.project.SourceGroup;
71
import org.netbeans.api.project.libraries.Library;
72
import org.netbeans.modules.j2ee.persistence.dd.persistence.model_1_0.PersistenceUnit;
73
import org.netbeans.modules.j2ee.persistence.provider.InvalidPersistenceXmlException;
74
import org.netbeans.modules.j2ee.persistence.provider.ProviderUtil;
75
import org.netbeans.modules.j2ee.persistence.spi.moduleinfo.JPAModuleInfo;
76
import org.netbeans.modules.j2ee.persistence.unit.PUDataObject;
77
import org.netbeans.modules.j2ee.persistence.wizard.entity.WrapperPanel;
78
import org.netbeans.modules.j2ee.persistence.wizard.unit.PersistenceUnitWizardPanel.TableGeneration;
79
import org.netbeans.modules.j2ee.persistence.wizard.unit.PersistenceUnitWizardPanel;
80
import org.netbeans.modules.j2ee.persistence.wizard.unit.PersistenceUnitWizardPanelDS;
81
import org.netbeans.modules.j2ee.persistence.wizard.unit.PersistenceUnitWizardPanelJdbc;
82
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
83
import org.netbeans.spi.java.project.classpath.ProjectClassPathExtender;
84
import org.openide.DialogDescriptor;
85
import org.openide.DialogDisplayer;
86
import org.openide.WizardDescriptor;
87
import org.openide.filesystems.FileObject;
88
import org.openide.filesystems.URLMapper;
89
import org.openide.util.Exceptions;
90
import org.openide.util.NbBundle;
93
* Copy of j2ee/utilities Util class
98
* Changes the text of a JLabel in component from oldLabel to newLabel
100
public static void changeLabelInComponent(JComponent component, String oldLabel, String newLabel) {
101
JLabel label = findLabel(component, oldLabel);
103
label.setText(newLabel);
108
* Hides a JLabel and the component that it is designated to labelFor, if any
110
public static void hideLabelAndLabelFor(JComponent component, String lab) {
111
JLabel label = findLabel(component, lab);
113
label.setVisible(false);
114
Component c = label.getLabelFor();
122
* Recursively gets all components in the components array and puts it in allComponents
124
public static void getAllComponents( Component[] components, Collection allComponents ) {
125
for( int i = 0; i < components.length; i++ ) {
126
if( components[i] != null ) {
127
allComponents.add( components[i] );
128
if( ( ( Container )components[i] ).getComponentCount() != 0 ) {
129
getAllComponents( ( ( Container )components[i] ).getComponents(), allComponents );
136
* Recursively finds a JLabel that has labelText in comp
138
public static JLabel findLabel(JComponent comp, String labelText) {
139
Vector allComponents = new Vector();
140
getAllComponents(comp.getComponents(), allComponents);
141
Iterator iterator = allComponents.iterator();
142
while(iterator.hasNext()) {
143
Component c = (Component)iterator.next();
144
if(c instanceof JLabel) {
145
JLabel label = (JLabel)c;
146
if(label.getText().equals(labelText)) {
155
* Returns the simple class for the passed fully-qualified class name.
157
public static String getClassName(String fqClassName) {
158
int dot = fqClassName.lastIndexOf("."); // NOI18N
159
if (dot >= 0 && dot < fqClassName.length() - 1) {
160
return fqClassName.substring(dot + 1);
167
* Returns the package name of the passed fully-qualified class name.
169
public static String getPackageName(String fqClassName) {
170
int dot = fqClassName.lastIndexOf("."); // NOI18N
171
if (dot >= 0 && dot < fqClassName.length() - 1) {
172
return fqClassName.substring(0, dot);
179
* Returns the SourceGroup of the passesd project which contains the
180
* fully-qualified class name.
182
public static SourceGroup getClassSourceGroup(Project project, String fqClassName) {
183
String classFile = fqClassName.replace('.', '/') + ".java"; // NOI18N
184
SourceGroup[] sourceGroups = ProjectUtils.getSources(project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
186
for (SourceGroup sourceGroup : sourceGroups) {
187
FileObject classFO = sourceGroup.getRootFolder().getFileObject(classFile);
188
if (classFO != null) {
196
* Returns Java source groups for all source packages in given project.<br>
197
* Doesn't include test packages.
199
* @param project Project to search
200
* @return Array of SourceGroup. It is empty if any probelm occurs.
202
public static SourceGroup[] getJavaSourceGroups(Project project) {
203
SourceGroup[] sourceGroups = ProjectUtils.getSources(project).getSourceGroups(
204
JavaProjectConstants.SOURCES_TYPE_JAVA);
205
Set testGroups = getTestSourceGroups(project, sourceGroups);
206
List result = new ArrayList();
207
for (int i = 0; i < sourceGroups.length; i++) {
208
if (!testGroups.contains(sourceGroups[i])) {
209
result.add(sourceGroups[i]);
212
return (SourceGroup[]) result.toArray(new SourceGroup[result.size()]);
215
private static Set/*<SourceGroup>*/ getTestSourceGroups(Project project, SourceGroup[] sourceGroups) {
216
Map foldersToSourceGroupsMap = createFoldersToSourceGroupsMap(sourceGroups);
217
Set testGroups = new HashSet();
218
for (int i = 0; i < sourceGroups.length; i++) {
219
testGroups.addAll(getTestTargets(sourceGroups[i], foldersToSourceGroupsMap));
224
private static Map createFoldersToSourceGroupsMap(final SourceGroup[] sourceGroups) {
226
if (sourceGroups.length == 0) {
227
result = Collections.EMPTY_MAP;
229
result = new HashMap(2 * sourceGroups.length, .5f);
230
for (int i = 0; i < sourceGroups.length; i++) {
231
SourceGroup sourceGroup = sourceGroups[i];
232
result.put(sourceGroup.getRootFolder(), sourceGroup);
238
private static List/*<FileObject>*/ getFileObjects(URL[] urls) {
239
List result = new ArrayList();
240
for (int i = 0; i < urls.length; i++) {
241
FileObject sourceRoot = URLMapper.findFileObject(urls[i]);
242
if (sourceRoot != null) {
243
result.add(sourceRoot);
244
} else if (Logger.getLogger("global").isLoggable(Level.FINE)) {
245
Logger.getLogger("global").log(Level.FINE, null, new IllegalStateException("No FileObject found for the following URL: " + urls[i]));
251
private static List/*<SourceGroup>*/ getTestTargets(SourceGroup sourceGroup, Map foldersToSourceGroupsMap) {
252
final URL[] rootURLs = UnitTestForSourceQuery.findUnitTests(sourceGroup.getRootFolder());
253
if (rootURLs.length == 0) {
254
return new ArrayList();
256
List result = new ArrayList();
257
List sourceRoots = getFileObjects(rootURLs);
258
for (int i = 0; i < sourceRoots.size(); i++) {
259
FileObject sourceRoot = (FileObject) sourceRoots.get(i);
260
SourceGroup srcGroup = (SourceGroup) foldersToSourceGroupsMap.get(sourceRoot);
261
if (srcGroup != null) {
262
result.add(srcGroup);
268
public static ClassPath getFullClasspath(FileObject fo) {
269
FileObject[] sourceRoots = ClassPath.getClassPath(fo, ClassPath.SOURCE).getRoots();
270
FileObject[] bootRoots = ClassPath.getClassPath(fo, ClassPath.BOOT).getRoots();
271
FileObject[] compileRoots = ClassPath.getClassPath(fo, ClassPath.COMPILE).getRoots();
272
FileObject[] roots = new FileObject[sourceRoots.length + bootRoots.length + compileRoots.length];
273
for (int i = 0; i < sourceRoots.length; i++) {
274
roots[i] = sourceRoots[i];
276
for (int i = 0; i < bootRoots.length; i++) {
277
roots[sourceRoots.length + i] = bootRoots[i];
279
for (int i = 0; i < compileRoots.length; i++) {
280
roots[sourceRoots.length + bootRoots.length + i] = compileRoots[i];
282
return ClassPathSupport.createClassPath(roots);
285
// from ejbcore utils
287
private static final String WIZARD_PANEL_CONTENT_DATA = "WizardPanel_contentData"; // NOI18N
288
private static final String WIZARD_PANEL_CONTENT_SELECTED_INDEX = "WizardPanel_contentSelectedIndex"; //NOI18N;
290
public static void mergeSteps(WizardDescriptor wizard, WizardDescriptor.Panel[] panels, String[] steps) {
291
Object prop = wizard.getProperty(WIZARD_PANEL_CONTENT_DATA);
292
String[] beforeSteps;
294
if (prop instanceof String[]) {
295
beforeSteps = (String[]) prop;
296
offset = beforeSteps.length;
297
if (offset > 0 && ("...".equals(beforeSteps[offset - 1]))) {// NOI18N
304
String[] resultSteps = new String[ (offset) + panels.length];
305
for (int i = 0; i < offset; i++) {
306
resultSteps[i] = beforeSteps[i];
308
setSteps(panels, steps, resultSteps, offset);
311
private static void setSteps(WizardDescriptor.Panel[] panels, String[] steps, String[] resultSteps, int offset) {
312
int n = steps == null ? 0 : steps.length;
313
for (int i = 0; i < panels.length; i++) {
314
final JComponent component = (JComponent) panels[i].getComponent();
315
String step = i < n ? steps[i] : null;
317
step = component.getName();
319
component.putClientProperty(WIZARD_PANEL_CONTENT_DATA, resultSteps);
320
component.putClientProperty(WIZARD_PANEL_CONTENT_SELECTED_INDEX, new Integer(i));
321
component.getAccessibleContext().setAccessibleDescription(step);
322
resultSteps[i + offset] = step;
326
public static void setSteps(WizardDescriptor.Panel[] panels, String[] steps) {
327
setSteps(panels, steps, steps, 0);
330
public static boolean isSupportedJavaEEVersion(Project project) {
331
JPAModuleInfo moduleInfo = project.getLookup().lookup(JPAModuleInfo.class);
332
if (moduleInfo == null){
335
if (JPAModuleInfo.ModuleType.EJB == moduleInfo.getType()
336
&& "3.0".equals(moduleInfo.getVersion())){
339
if (JPAModuleInfo.ModuleType.WEB == moduleInfo.getType()
340
&& "2.5".equals(moduleInfo.getVersion())){
346
public static boolean isEjbModule(Project project) {
347
JPAModuleInfo moduleInfo = project.getLookup().lookup(JPAModuleInfo.class);
348
if (moduleInfo == null){
351
return JPAModuleInfo.ModuleType.EJB == moduleInfo.getType();
355
public static boolean isEjb21Module(Project project) {
356
JPAModuleInfo moduleInfo = project.getLookup().lookup(JPAModuleInfo.class);
357
if (moduleInfo == null){
361
return JPAModuleInfo.ModuleType.EJB == moduleInfo.getType()
362
&& "2.1".equals(moduleInfo.getVersion());
366
* @return true if given this data object's project's enviroment is Java SE, false otherwise.
368
public static boolean isJavaSE(Project project){
369
return project.getLookup().lookup(JPAModuleInfo.class) == null;
373
* Builds a persistence unit using wizard. Does not save the created persistence unit
374
* nor create the persistence.xml file if it does not exist.
375
* @param project the current project
376
* @param preselectedDB the name of the database connection that should be preselected in the wizard.
377
* @tableGeneration the table generation strategy that should be preselected in the wizard.
378
* @return the created PersistenceUnit or null if nothing was created, for example
379
* if wizard was cancelled.
381
public static PersistenceUnit buildPersistenceUnitUsingWizard(Project project,
382
String preselectedDB, TableGeneration tableGeneration){
384
boolean isContainer = Util.isSupportedJavaEEVersion(project);
385
PersistenceUnitWizardPanel panel;
387
panel = new PersistenceUnitWizardPanelDS(project, null, true, tableGeneration);
389
panel = new PersistenceUnitWizardPanelJdbc(project, null, true, tableGeneration);
391
if (preselectedDB != null) {
392
panel.setPreselectedDB(preselectedDB);
395
final JButton createPUButton = new JButton(NbBundle.getMessage(Util.class,"LBL_CreatePersistenceUnitButton"));
396
createPUButton.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(Util.class,"ACSD_CreatePersistenceUnitButton"));
397
Object[] buttons = new Object[] { createPUButton, DialogDescriptor.CANCEL_OPTION };
399
final DialogDescriptor nd = new DialogDescriptor(
400
new WrapperPanel(panel),
401
NbBundle.getMessage(Util.class, "LBL_CreatePersistenceUnit"),
404
DialogDescriptor.OK_OPTION,
405
DialogDescriptor.DEFAULT_ALIGN,
409
panel.addPropertyChangeListener(new PropertyChangeListener() {
410
public void propertyChange(PropertyChangeEvent evt) {
411
if (evt.getPropertyName().equals(PersistenceUnitWizardPanel.IS_VALID)) {
412
Object newvalue = evt.getNewValue();
413
if ((newvalue != null) && (newvalue instanceof Boolean)) {
414
nd.setValid(((Boolean)newvalue).booleanValue());
415
createPUButton.setEnabled(((Boolean)newvalue).booleanValue());
420
if (!panel.isValidPanel()) {
422
createPUButton.setEnabled(false);
424
Object result = DialogDisplayer.getDefault().notify(nd);
425
if (result == createPUButton) {
426
PersistenceUnit punit = new PersistenceUnit();
428
PersistenceUnitWizardPanelDS puPanel = (PersistenceUnitWizardPanelDS) panel;
429
if (puPanel.getDatasource() != null && !"".equals(puPanel.getDatasource().trim())){
430
if (puPanel.isJTA()) {
431
punit.setJtaDataSource(puPanel.getDatasource());
433
if (puPanel.isNonDefaultProviderEnabled()) {
434
punit.setNonJtaDataSource(puPanel.getDatasource());
436
punit.setTransactionType("RESOURCE_LOCAL");
439
if (puPanel.isNonDefaultProviderEnabled()) {
440
punit.setProvider(puPanel.getNonDefaultProvider());
443
PersistenceUnitWizardPanelJdbc puJdbc = (PersistenceUnitWizardPanelJdbc) panel;
444
punit = ProviderUtil.buildPersistenceUnit(puJdbc.getPersistenceUnitName(), puJdbc.getSelectedProvider(), puJdbc.getPersistenceConnection());
445
punit.setTransactionType("RESOURCE_LOCAL"); //NO18N
446
if (puJdbc.getPersistenceLibrary() != null){
447
addLibraryToProject(project, puJdbc.getPersistenceLibrary());
450
punit.setName(panel.getPersistenceUnitName());
451
ProviderUtil.setTableGeneration(punit, panel.getTableGeneration(), project);
459
* Creates a persistence unit using the PU wizard and adds the created
460
* persistence unit to the given project's <code>PUDataObject</code> and saves it.
462
* @param project the project to which the created persistence unit is to be created.
463
* @param preselectedDB the name of the db connection that should be preselected, or null if none needs
465
* @param tableGeneration the table generation strategy for the persistence unit.
467
* @return true if the creation of the persistence unit was successful, false otherwise.
469
* @throws InvalidPersistenceXmlException if the persistence.xml file in the given
470
* project is not valid.
473
public static boolean createPersistenceUnitUsingWizard(Project project,
474
String preselectedDB, TableGeneration tableGeneration) throws InvalidPersistenceXmlException {
476
PersistenceUnit punit = buildPersistenceUnitUsingWizard(project, preselectedDB, tableGeneration);
480
PUDataObject pud = ProviderUtil.getPUDataObject(project);
481
pud.addPersistenceUnit(punit);
487
* Creates a persistence unit with the default table generation strategy using the PU wizard and adds the created
488
* persistence unit to the given project's <code>PUDataObject</code> and saves it.
490
* @param project the project to which the created persistence unit is to be created.
491
* @param preselectedDB the name of the db connection that should be preselected, or null if none needs
494
* @return true if the creation of the persistence unit was successful, false otherwise.
496
* @throws InvalidPersistenceXmlException if the persistence.xml file in the given
497
* project is not valid.
500
public static boolean createPersistenceUnitUsingWizard(Project project, String preselectedDB) throws InvalidPersistenceXmlException {
501
return createPersistenceUnitUsingWizard(project, preselectedDB, TableGeneration.CREATE);
504
public static void addLibraryToProject(Project project, Library library) {
505
ProjectClassPathExtender pcpe = (ProjectClassPathExtender) project.getLookup().lookup(ProjectClassPathExtender.class);
508
pcpe.addLibrary(library);
509
} catch (IOException ex) {
510
Exceptions.printStackTrace(ex);
515
public static String simpleClassName(String fqn) {
516
int lastDot = fqn.lastIndexOf('.');
517
return lastDot > 0 ? fqn.substring(lastDot + 1) : fqn;