This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 154427
Collapse All | Expand All

(-)a/projectui/src/org/netbeans/modules/project/ui/OpenProjectList.java (-4 / +40 lines)
Lines 91-96 Link Here
91
import org.netbeans.modules.project.uiapi.ProjectOpenedTrampoline;
91
import org.netbeans.modules.project.uiapi.ProjectOpenedTrampoline;
92
import org.netbeans.spi.project.SubprojectProvider;
92
import org.netbeans.spi.project.SubprojectProvider;
93
import org.netbeans.spi.project.ui.PrivilegedTemplates;
93
import org.netbeans.spi.project.ui.PrivilegedTemplates;
94
import org.netbeans.spi.project.ui.ProjectInitializationHook;
94
import org.netbeans.spi.project.ui.ProjectOpenedHook;
95
import org.netbeans.spi.project.ui.ProjectOpenedHook;
95
import org.netbeans.spi.project.ui.RecommendedTemplates;
96
import org.netbeans.spi.project.ui.RecommendedTemplates;
96
import org.openide.ErrorManager;
97
import org.openide.ErrorManager;
Lines 220-225 Link Here
220
            }
221
            }
221
        }
222
        }
222
        return wrap;
223
        return wrap;
224
    }
225
226
    private static Project doInitializeProject(Project p) {
227
        ClassLoader l = ProjectOpenedHook.class.getClassLoader();
228
        try {
229
            Class.forName(ProjectOpenedHook.class.getName(), true, l);
230
        } catch (ClassNotFoundException ex) {
231
            Exceptions.printStackTrace(ex);
232
        }
233
        INIT: for (;;) {
234
            Collection<? extends ProjectInitializationHook> initHooks = p.getLookup().lookupAll(ProjectInitializationHook.class);
235
            assert initHooks.size() <= 1 : "There can be at most one hook " + initHooks;
236
            for (ProjectInitializationHook h : initHooks) {
237
                Project np = ProjectOpenedTrampoline.DEFAULT.projectWillBeOpened(h);
238
                if (np == null) {
239
                    return np;
240
                }
241
                if (np != p) {
242
                    p = np;
243
                    continue INIT;
244
                }
245
            }
246
            return p;
247
        }
223
    }
248
    }
224
249
225
    /** Modifications to the recentTemplates variables shall be done only 
250
    /** Modifications to the recentTemplates variables shall be done only 
Lines 352-357 Link Here
352
                    }
377
                    }
353
                    p = toOpenProjects.remove();
378
                    p = toOpenProjects.remove();
354
                    LOGGER.log(Level.FINER, "after remove {0}", toOpenProjects); // NOI18N
379
                    LOGGER.log(Level.FINER, "after remove {0}", toOpenProjects); // NOI18N
380
                }
381
                LOGGER.log(Level.FINE, "about to init a project {0}", p); // NOI18N
382
                p = doInitializeProject(p);
383
                if (p == null) {
384
                    LOGGER.log(Level.FINE, "project shall not be opened"); // NOI18N
385
                    continue;
355
                }
386
                }
356
                LOGGER.log(Level.FINE, "about to open a project {0}", p); // NOI18N
387
                LOGGER.log(Level.FINE, "about to open a project {0}", p); // NOI18N
357
                if (notifyOpened(p)) {
388
                if (notifyOpened(p)) {
Lines 1031-1039 Link Here
1031
        }
1062
        }
1032
    }
1063
    }
1033
    
1064
    
1034
    private boolean doOpenProject(final Project p) {
1065
    private boolean doOpenProject(Project p) {
1035
        boolean recentProjectsChanged;
1066
        boolean recentProjectsChanged;
1036
        LOGGER.finer("doOpenProject(): opening project " + p.toString());
1067
        LOGGER.finer("doOpenProject(): opening project " + p.toString());
1068
        p = doInitializeProject(p);
1069
        if (p == null) {
1070
            return false;
1071
        }
1072
1037
        synchronized (this) {
1073
        synchronized (this) {
1038
            if (openProjects.contains(p)) {
1074
            if (openProjects.contains(p)) {
1039
                return false;
1075
                return false;
Lines 1049-1060 Link Here
1049
        logProjects("doOpenProject(): openProjects == ", openProjects.toArray(new Project[0])); // NOI18N
1085
        logProjects("doOpenProject(): openProjects == ", openProjects.toArray(new Project[0])); // NOI18N
1050
        // Notify projects opened
1086
        // Notify projects opened
1051
        notifyOpened(p);
1087
        notifyOpened(p);
1052
        
1088
1089
        final Project openFilesFor = p;
1053
        Mutex.EVENT.readAccess(new Action<Void>() {
1090
        Mutex.EVENT.readAccess(new Action<Void>() {
1054
            public Void run() {
1091
            public Void run() {
1055
                // Open project files
1092
                // Open project files
1056
                ProjectUtilities.openProjectFiles(p);
1093
                ProjectUtilities.openProjectFiles(openFilesFor);
1057
                
1058
                return null;
1094
                return null;
1059
            }
1095
            }
1060
        });
1096
        });
(-)f4a875afac55 (+274 lines)
Added Link Here
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-2006 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.project.ui;
43
44
import java.io.IOException;
45
import java.util.concurrent.TimeUnit;
46
import java.util.concurrent.TimeoutException;
47
import java.util.logging.Level;
48
import org.netbeans.api.project.Project;
49
import org.netbeans.api.project.ProjectManager;
50
import org.netbeans.api.project.ui.OpenProjects;
51
import org.netbeans.junit.MockServices;
52
import org.netbeans.junit.NbTestCase;
53
import org.netbeans.spi.project.ProjectFactory;
54
import org.netbeans.spi.project.ProjectState;
55
import org.netbeans.spi.project.ui.ProjectInitializationHook;
56
import org.netbeans.spi.project.ui.ProjectOpenedHook;
57
import org.openide.filesystems.FileObject;
58
import org.openide.filesystems.FileUtil;
59
import org.openide.util.Exceptions;
60
import org.openide.util.Lookup;
61
import org.openide.util.RequestProcessor;
62
import org.openide.util.lookup.AbstractLookup;
63
import org.openide.util.lookup.InstanceContent;
64
65
/** Verify ProjectInitializationHook is called.
66
 *
67
 * @author Jaroslav Tulach
68
 */
69
public class OpenProjectInitializeTest extends NbTestCase {
70
    FileObject f1_1_open, f1_2_open, f1_3_close;
71
    FileObject f2_1_open;
72
73
    Project project1;
74
75
    public OpenProjectInitializeTest (String testName) {
76
        super (testName);
77
    }
78
79
    @Override
80
    protected Level logLevel() {
81
        return Level.FINE;
82
    }
83
84
    @Override
85
    protected void setUp () throws Exception {
86
        super.setUp ();
87
        MockServices.setServices(MyFactory.class);
88
        clearWorkDir ();
89
        
90
        FileObject workDir = FileUtil.toFileObject (getWorkDir ());
91
    
92
        FileObject p1 = workDir.createFolder("prjDir");
93
        f1_1_open = p1.createData("f1_1.java");
94
        f1_2_open = p1.createData("f1_2.java");
95
        f1_3_close = p1.createData("f1_3.java");
96
97
        MyFactory.toRet = new MyProject(p1);
98
        project1 = ProjectManager.getDefault ().findProject (p1);
99
        assertNotNull("Project found", project1);
100
101
        assertEquals("No open prjs", 0, OpenProjects.getDefault().openProjects().get().length);
102
    }
103
    
104
    @Override
105
    protected void tearDown () throws Exception {
106
        OpenProjectList.getDefault().close(OpenProjectList.getDefault().getOpenProjects(), false);
107
        assertEquals("No open prjs", 0, OpenProjects.getDefault().openProjects().get().length);
108
    }
109
110
    public void testOpenWithOneRedirect() throws Exception {
111
        assertTrue ("No project is open.", OpenProjectList.getDefault ().getOpenProjects ().length == 0);
112
113
        MyProject project2 = new MyProject(project1.getProjectDirectory());
114
115
        InitHook h = new InitHook(project2);
116
        MyProject tp = (MyProject)project1;
117
        h.stateToClose = tp.state;
118
        tp.ic.add(h);
119
120
        OpenProjectList.getDefault ().open(tp, true);
121
122
        Project[] open = OpenProjectList.getDefault().getOpenProjects();
123
        assertEquals("One is open", 1, open.length);
124
        assertEquals("Redirect gets opened", project2, open[0]);
125
        assertEquals("Its open hook is called", 1, project2.openHook.opened);
126
        assertEquals("Open hook of project1 ignored", 0, tp.openHook.opened);
127
    }
128
129
    public void testOpenWithTwoRedirect() throws Exception {
130
        assertTrue ("No project is open.", OpenProjectList.getDefault ().getOpenProjects ().length == 0);
131
132
        MyProject project2 = new MyProject(project1.getProjectDirectory());
133
        MyProject project3 = new MyProject(project1.getProjectDirectory());
134
135
        InitHook h = new InitHook(project2);
136
        InitHook h2 = new InitHook(project3);
137
        MyProject tp = (MyProject)project1;
138
        h2.stateToClose = tp.state;
139
        tp.ic.add(h2);
140
        project2.ic.add(h2);
141
142
        OpenProjectList.getDefault ().open (tp, true);
143
144
        Project[] open = OpenProjectList.getDefault().getOpenProjects();
145
        assertEquals("One is open", 1, open.length);
146
        assertEquals("Project3 gets opened", project3, open[0]);
147
        assertEquals("Project3 open hook is called", 1, project3.openHook.opened);
148
        assertEquals("Project2 open hook is ignored", 0, project2.openHook.opened);
149
        assertEquals("Open hook of project1 ignored", 0, tp.openHook.opened);
150
    }
151
152
    public void testNullOpensNoProject() throws Exception {
153
        assertTrue ("No project is open.", OpenProjectList.getDefault ().getOpenProjects ().length == 0);
154
155
        InitHook h = new InitHook(null);
156
        MyProject tp = (MyProject)project1;
157
        tp.ic.add(h);
158
159
        OpenProjectList.getDefault ().open (tp, true);
160
161
        Project[] open = OpenProjectList.getDefault().getOpenProjects();
162
        assertEquals("Nothing is open", 0, open.length);
163
        assertEquals("Open hook of project1 ignored", 0, tp.openHook.opened);
164
    }
165
166
    public static class MyFactory implements ProjectFactory {
167
        static MyProject toRet;
168
169
        public boolean isProject(FileObject d) {
170
            return toRet != null && toRet.getProjectDirectory().equals(d);
171
        }
172
173
        public Project loadProject(FileObject projectDirectory, ProjectState state) throws IOException {
174
            if (toRet != null && projectDirectory.equals(toRet.getProjectDirectory())) {
175
                MyProject h = toRet;
176
                h.state = state;
177
                toRet = null;
178
                return h;
179
            }
180
            return null;
181
        }
182
183
        public void saveProject(Project project) throws IOException, ClassCastException {
184
        }
185
    } // end of MyFactory
186
187
188
189
    private static class MyProject implements Project {
190
        final FileObject fo;
191
        final Lookup lookup;
192
        final InstanceContent ic;
193
        final OpenHook openHook;
194
        ProjectState state;
195
196
        public MyProject(FileObject fo) {
197
            this.fo = fo;
198
            this.ic = new InstanceContent();
199
            this.lookup = new AbstractLookup(ic);
200
            this.openHook = new OpenHook();
201
            ic.add(openHook);
202
        }
203
204
        public FileObject getProjectDirectory() {
205
            return fo;
206
        }
207
208
        public Lookup getLookup() {
209
            return lookup;
210
        }
211
    } // end of MyProject
212
    private static class InitHook extends ProjectInitializationHook {
213
        MyProject willBeOpened;
214
        ProjectState stateToClose;
215
        public InitHook(MyProject next) {
216
            willBeOpened = next;
217
        }
218
219
        @Override
220
        protected Project projectWillBeOpened() {
221
            if (stateToClose != null) {
222
                stateToClose.notifyDeleted();
223
                stateToClose = null;
224
            }
225
            if (willBeOpened == null) {
226
                return null;
227
            }
228
            try {
229
                MyFactory.toRet = willBeOpened;
230
                Project found = ProjectManager.getDefault().findProject(willBeOpened.getProjectDirectory());
231
                assertEquals("The right one found", willBeOpened, found);
232
                return found;
233
            } catch (IOException ex) {
234
                Exceptions.printStackTrace(ex);
235
            } catch (IllegalArgumentException ex) {
236
                Exceptions.printStackTrace(ex);
237
            }
238
            return null;
239
        }
240
    } // end of InitHook
241
    private static class OpenHook extends ProjectOpenedHook
242
    implements Runnable {
243
        int opened = 0;
244
        int closed = 0;
245
        
246
        private Object result;
247
        
248
        protected void projectClosed() {
249
            closed++;
250
            assertFalse("Working on", OpenProjects.getDefault().openProjects().isDone());
251
            RequestProcessor.getDefault().post(this).waitFinished();
252
            assertNotNull("some result computed", result);
253
            assertEquals("It is time out exception", TimeoutException.class, result.getClass());
254
        }
255
        
256
        protected void projectOpened() {
257
            opened++;
258
            assertFalse("Working on", OpenProjects.getDefault().openProjects().isDone());
259
            RequestProcessor.getDefault().post(this).waitFinished();
260
            assertNotNull("some result computed", result);
261
            assertEquals("It is time out exception", TimeoutException.class, result.getClass());
262
        }
263
        
264
        public void run() {
265
            try {
266
                result = OpenProjects.getDefault().openProjects().get(100, TimeUnit.MILLISECONDS);
267
            } catch (Exception ex) {
268
                result = ex;
269
    }
270
        }
271
    }
272
273
    
274
}
(-)a/projectuiapi/apichanges.xml (+17 lines)
Lines 104-109 Link Here
104
    <!-- ACTUAL CHANGES BEGIN HERE: -->
104
    <!-- ACTUAL CHANGES BEGIN HERE: -->
105
105
106
    <changes>
106
    <changes>
107
        <change id="ProjectInitializationHook">
108
            <api name="general"/>
109
            <summary>Add ProjectInitializationHook</summary>
110
            <version major="1" minor="34"/>
111
            <date day="20" month="12" year="2008"/>
112
            <author login="jtulach"/>
113
            <compatibility addition="yes" binary="compatible" deletion="no" deprecation="no" modification="no" semantic="compatible" source="compatible"/>
114
            <description>
115
                <p>
116
                <code>ProjectInitializationHook</code> can be provided by Project's
117
                to be notified that the project is about to become opened and
118
                prevent that by finding proper substitute.
119
                </p>
120
            </description>
121
            <class package="org.netbeans.spi.project.ui" name="ProjectInitializationHook"/>
122
            <issue number="154427"/>
123
        </change>
107
        <change id="nodefactory-ann">
124
        <change id="nodefactory-ann">
108
            <api name="general"/>
125
            <api name="general"/>
109
            <summary>Add annotation @NodeFactory.Registration</summary>
126
            <summary>Add annotation @NodeFactory.Registration</summary>
(-)a/projectuiapi/nbproject/project.properties (-1 / +1 lines)
Lines 39-45 Link Here
39
39
40
javac.compilerargs=-Xlint -Xlint:-serial
40
javac.compilerargs=-Xlint -Xlint:-serial
41
javac.source=1.5
41
javac.source=1.5
42
spec.version.base=1.33.0
42
spec.version.base=1.34.0
43
is.autoload=true
43
is.autoload=true
44
javadoc.arch=${basedir}/arch.xml
44
javadoc.arch=${basedir}/arch.xml
45
javadoc.apichanges=${basedir}/apichanges.xml
45
javadoc.apichanges=${basedir}/apichanges.xml
(-)a/projectuiapi/src/org/netbeans/modules/project/uiapi/ProjectOpenedTrampoline.java (+5 lines)
Lines 41-46 Link Here
41
41
42
package org.netbeans.modules.project.uiapi;
42
package org.netbeans.modules.project.uiapi;
43
43
44
import org.netbeans.api.project.Project;
45
import org.netbeans.spi.project.ui.ProjectInitializationHook;
44
import org.netbeans.spi.project.ui.ProjectOpenedHook;
46
import org.netbeans.spi.project.ui.ProjectOpenedHook;
45
47
46
/**
48
/**
Lines 62-67 Link Here
62
    
64
    
63
    /** Used by {@link ProjectOpenedHook}. */
65
    /** Used by {@link ProjectOpenedHook}. */
64
    protected ProjectOpenedTrampoline() {}
66
    protected ProjectOpenedTrampoline() {}
67
68
    /** Delegates to {@link ProjectInitializationHook#projectWillBeOpened()}. */
69
    public abstract Project projectWillBeOpened(ProjectInitializationHook hook);
65
    
70
    
66
    /** Delegates to {@link ProjectOpenedHook#projectOpened}. */
71
    /** Delegates to {@link ProjectOpenedHook#projectOpened}. */
67
    public abstract void projectOpened(ProjectOpenedHook hook);
72
    public abstract void projectOpened(ProjectOpenedHook hook);
(-)f4a875afac55 (+76 lines)
Added Link Here
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-2006 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.spi.project.ui;
43
44
import org.netbeans.api.project.Project;
45
46
/**
47
 * A hook which can be run when a project is about to be "opened" the GUI.
48
 * Called before {@link ProjectOpenedHook}'s <code>projectOpened</code> method
49
 * is called. Register an instance of this class into {@link Project#getLookup()}
50
 * method to perform pre-initialization actions, including finding another 
51
 * project to represent this directory.
52
 * </p>
53
 * @see ProjectOpenedHook#projectOpened
54
 * @see org.netbeans.api.project.Project#getLookup
55
 * 
56
 * @author Jaroslav Tulach
57
 * @since 1.34
58
 */
59
public abstract class ProjectInitializationHook {
60
    /**
61
     * Default constructor for use by subclasses.
62
     */
63
    protected ProjectInitializationHook() {}
64
    
65
    /**
66
     * Called when a project is about to be open in the GUI. The project has
67
     * a chance to initialize necessary system resources and potentially
68
     * also provide a delegate that shall be open instead of the project
69
     * itself.
70
     *
71
     * @return either project that shall be installed instead of the one
72
     *   providing this hook, the project itself, or
73
     *   <code>null</code> which means that no project will be opened at all
74
     */
75
    protected abstract Project projectWillBeOpened();
76
}
(-)a/projectuiapi/src/org/netbeans/spi/project/ui/ProjectOpenedHook.java (+6 lines)
Lines 41-46 Link Here
41
41
42
package org.netbeans.spi.project.ui;
42
package org.netbeans.spi.project.ui;
43
43
44
import org.netbeans.api.project.Project;
44
import org.netbeans.modules.project.uiapi.ProjectOpenedTrampoline;
45
import org.netbeans.modules.project.uiapi.ProjectOpenedTrampoline;
45
46
46
/**
47
/**
Lines 82-87 Link Here
82
            }
83
            }
83
            public void projectClosed(ProjectOpenedHook hook) {
84
            public void projectClosed(ProjectOpenedHook hook) {
84
                hook.projectClosed();
85
                hook.projectClosed();
86
            }
87
88
            @Override
89
            public Project projectWillBeOpened(ProjectInitializationHook hook) {
90
                return hook.projectWillBeOpened();
85
            }
91
            }
86
        };
92
        };
87
    }
93
    }

Return to bug 154427