~ubuntu-branches/ubuntu/quantal/netbeans/quantal

« back to all changes in this revision

Viewing changes to java/j2seproject/src/org/netbeans/modules/java/j2seproject/MainClassUpdater.java

  • Committer: Bazaar Package Importer
  • Author(s): Marek Slama
  • Date: 2008-01-29 14:11:22 UTC
  • Revision ID: james.westby@ubuntu.com-20080129141122-fnzjbo11ntghxfu7
Tags: upstream-6.0.1
ImportĀ upstreamĀ versionĀ 6.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
3
 *
 
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 
5
 *
 
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]"
 
23
 *
 
24
 * Contributor(s):
 
25
 *
 
26
 * The Original Software is NetBeans. The Initial Developer of the Original
 
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
 
28
 * Microsystems, Inc. All Rights Reserved.
 
29
 *
 
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.
 
40
 */
 
41
 
 
42
package org.netbeans.modules.java.j2seproject;
 
43
 
 
44
import java.beans.PropertyChangeEvent;
 
45
import java.beans.PropertyChangeListener;
 
46
import java.io.IOException;
 
47
import java.util.Collection;
 
48
import javax.lang.model.element.TypeElement;
 
49
import javax.swing.SwingUtilities;
 
50
import org.netbeans.api.java.classpath.ClassPath;
 
51
import org.netbeans.api.java.source.Task;
 
52
import org.netbeans.api.java.source.ClasspathInfo;
 
53
import org.netbeans.api.java.source.CompilationController;
 
54
import org.netbeans.api.java.source.CompilationController;
 
55
import org.netbeans.api.java.source.ElementHandle;
 
56
import org.netbeans.api.java.source.JavaSource;
 
57
import org.netbeans.api.java.source.SourceUtils;
 
58
import org.netbeans.api.project.Project;
 
59
import org.netbeans.api.project.ProjectManager;
 
60
import org.netbeans.spi.project.support.ant.AntProjectHelper;
 
61
import org.netbeans.spi.project.support.ant.EditableProperties;
 
62
import org.netbeans.spi.project.support.ant.PropertyEvaluator;
 
63
import org.openide.filesystems.FileChangeAdapter;
 
64
import org.openide.filesystems.FileObject;
 
65
import org.openide.filesystems.FileRenameEvent;
 
66
import org.openide.util.Exceptions;
 
67
import org.openide.util.Mutex;
 
68
import org.openide.util.MutexException;
 
69
import org.openide.util.RequestProcessor;
 
70
 
 
71
/**
 
72
 *
 
73
 * @author Tomas Zezula
 
74
 */
 
75
public class MainClassUpdater extends FileChangeAdapter implements PropertyChangeListener {
 
76
    
 
77
    private static final RequestProcessor RP = new RequestProcessor ("main-class-updater",1);       //NOI18N
 
78
    
 
79
    private final Project project;
 
80
    private final PropertyEvaluator eval;
 
81
    private final UpdateHelper helper;
 
82
    private final ClassPath sourcePath;
 
83
    private final String mainClassPropName;
 
84
    private FileObject current;
 
85
    
 
86
    /** Creates a new instance of MainClassUpdater */
 
87
    public MainClassUpdater(final Project project, final PropertyEvaluator eval,
 
88
        final UpdateHelper helper, final ClassPath sourcePath, final String mainClassPropName) {
 
89
        assert project != null;
 
90
        assert eval != null;
 
91
        assert helper != null;
 
92
        assert sourcePath != null;
 
93
        assert mainClassPropName != null;
 
94
        this.project = project;
 
95
        this.eval = eval;
 
96
        this.helper = helper;
 
97
        this.sourcePath = sourcePath;
 
98
        this.mainClassPropName = mainClassPropName;
 
99
        this.eval.addPropertyChangeListener(this);
 
100
        this.addFileChangeListener ();
 
101
    }
 
102
    
 
103
    public synchronized void unregister () {
 
104
        if (current != null) {
 
105
            current.removeFileChangeListener(this);
 
106
        }
 
107
    }
 
108
    
 
109
    public void propertyChange(PropertyChangeEvent evt) {
 
110
        if (this.mainClassPropName.equals(evt.getPropertyName())) {
 
111
            //Go out of the ProjectManager.MUTEX, see #118722
 
112
            RP.post(new Runnable () {
 
113
                public void run() {
 
114
                    MainClassUpdater.this.addFileChangeListener ();
 
115
                }
 
116
            });            
 
117
        }
 
118
    }
 
119
    
 
120
    @Override
 
121
    public void fileRenamed (final FileRenameEvent evt) {
 
122
        final FileObject _current;
 
123
        synchronized (this) {
 
124
            _current = this.current;
 
125
        }
 
126
        if (evt.getFile() == _current) {
 
127
            Runnable r = new Runnable () {
 
128
                public void run () {  
 
129
                    try {
 
130
                        final String oldMainClass = ProjectManager.mutex().readAccess(new Mutex.ExceptionAction<String>() {
 
131
                            public String run() throws Exception {
 
132
                                return eval.getProperty(mainClassPropName);
 
133
                            }
 
134
                        });
 
135
 
 
136
                        Collection<ElementHandle<TypeElement>> main = SourceUtils.getMainClasses(_current);
 
137
                        String newMainClass = null;
 
138
                        if (!main.isEmpty()) {
 
139
                            ElementHandle<TypeElement> mainHandle = main.iterator().next();
 
140
                            newMainClass = mainHandle.getQualifiedName();
 
141
                        }                    
 
142
                        if (newMainClass != null && !newMainClass.equals(oldMainClass) && helper.requestSave() &&
 
143
                                // XXX ##84806: ideally should update nbproject/configs/*.properties in this case:
 
144
                            eval.getProperty(J2SEConfigurationProvider.PROP_CONFIG) == null) {
 
145
                            final String newMainClassFinal = newMainClass;
 
146
                            ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Void>() {
 
147
                                public Void run() throws Exception {                                                                                    
 
148
                                    EditableProperties props = helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
 
149
                                    props.put (mainClassPropName, newMainClassFinal);
 
150
                                    helper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props);
 
151
                                    ProjectManager.getDefault().saveProject (project);
 
152
                                    return null;
 
153
                                }
 
154
                            });
 
155
                        }
 
156
                    } catch (IOException e) {
 
157
                        Exceptions.printStackTrace(e);
 
158
                    }
 
159
                    catch (MutexException e) {
 
160
                        Exceptions.printStackTrace(e);
 
161
                    }
 
162
                }
 
163
            };
 
164
            if (SwingUtilities.isEventDispatchThread()) {
 
165
                r.run();
 
166
            }
 
167
            else {
 
168
                SwingUtilities.invokeLater(r);
 
169
            }
 
170
        }
 
171
    }
 
172
    
 
173
    private void addFileChangeListener () {
 
174
        synchronized (MainClassUpdater.this) {
 
175
            if (current != null) {
 
176
                current.removeFileChangeListener(MainClassUpdater.this);
 
177
                current = null;
 
178
            }            
 
179
        }
 
180
        final String mainClassName = org.netbeans.modules.java.j2seproject.MainClassUpdater.this.eval.getProperty(mainClassPropName);
 
181
        if (mainClassName != null) {
 
182
            try {
 
183
                FileObject[] roots = sourcePath.getRoots();
 
184
                if (roots.length>0) {
 
185
                    ClassPath bootCp = ClassPath.getClassPath(roots[0], ClassPath.BOOT);
 
186
                    ClassPath compileCp = ClassPath.getClassPath(roots[0], ClassPath.COMPILE);
 
187
                    final ClasspathInfo cpInfo = ClasspathInfo.create(bootCp, compileCp, sourcePath);
 
188
                    JavaSource js = JavaSource.create(cpInfo);
 
189
                    js.runWhenScanFinished(new Task<CompilationController>() {
 
190
 
 
191
                        public void run(CompilationController c) throws Exception {
 
192
                            TypeElement te = c.getElements().getTypeElement(mainClassName);
 
193
                             if (te != null) {
 
194
                                synchronized (MainClassUpdater.this) {
 
195
                                    current = SourceUtils.getFile(te, cpInfo);
 
196
                                    if (current != null && sourcePath.contains(current)) {
 
197
                                        current.addFileChangeListener(MainClassUpdater.this);
 
198
                                    }
 
199
                                }
 
200
                            }                            
 
201
                        }
 
202
 
 
203
                    }, true);
 
204
                }
 
205
            } catch (IOException ioe) {
 
206
            }
 
207
        }        
 
208
    }
 
209
 
 
210
}