001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * If you wish your version of this file to be governed by only the CDDL
025: * or only the GPL Version 2, indicate your decision by adding
026: * "[Contributor] elects to include this software in this distribution
027: * under the [CDDL or GPL Version 2] license." If you do not indicate a
028: * single choice of license, a recipient has the option to distribute
029: * your version of this file under either the CDDL, the GPL Version 2 or
030: * to extend the choice of license to its licensees as provided above.
031: * However, if you add GPL Version 2 code and therefore, elected the GPL
032: * Version 2 license, then the option applies only if the new code is
033: * made subject to such option by the copyright holder.
034: *
035: * Contributor(s):
036: *
037: * Portions Copyrighted 2007 Sun Microsystems, Inc.
038: */
039:
040: package org.netbeans.modules.project.ui;
041:
042: import java.awt.EventQueue;
043: import java.beans.PropertyChangeEvent;
044: import java.beans.PropertyChangeListener;
045: import java.io.IOException;
046: import java.net.URL;
047: import java.util.ArrayList;
048: import java.util.EventObject;
049: import java.util.List;
050: import java.util.concurrent.CountDownLatch;
051: import javax.swing.Icon;
052: import javax.swing.event.ChangeListener;
053: import org.netbeans.api.project.Project;
054: import org.netbeans.api.project.ProjectManager;
055: import org.netbeans.api.project.SourceGroup;
056: import org.netbeans.api.project.Sources;
057: import org.netbeans.junit.MockServices;
058: import org.netbeans.junit.NbTestCase;
059: import org.netbeans.modules.project.ui.actions.TestSupport;
060: import org.netbeans.spi.project.ui.LogicalViewProvider;
061: import org.netbeans.spi.project.ui.ProjectOpenedHook;
062: import org.openide.filesystems.FileObject;
063: import org.openide.filesystems.FileUtil;
064: import org.openide.filesystems.URLMapper;
065: import org.openide.nodes.AbstractNode;
066: import org.openide.nodes.Children;
067: import org.openide.nodes.Node;
068: import org.openide.nodes.NodeEvent;
069: import org.openide.nodes.NodeListener;
070: import org.openide.nodes.NodeMemberEvent;
071: import org.openide.nodes.NodeReorderEvent;
072: import org.openide.util.lookup.Lookups;
073: import org.openidex.search.SearchInfo;
074:
075: /**
076: *
077: * @author Jaroslav Tulach <jtulach@netbeans.org>
078: */
079: public class ProjectsRootNodePhysicalViewModeSourcesTest extends
080: NbTestCase {
081: CountDownLatch down;
082:
083: public ProjectsRootNodePhysicalViewModeSourcesTest(String testName) {
084: super (testName);
085: }
086:
087: @Override
088: protected void setUp() throws Exception {
089: clearWorkDir();
090:
091: MockServices.setServices(TestSupport.TestProjectFactory.class);
092:
093: FileObject workDir = FileUtil.toFileObject(getWorkDir());
094: assertNotNull(workDir);
095:
096: down = new CountDownLatch(1);
097:
098: List<URL> list = new ArrayList<URL>();
099: List<ExtIcon> icons = new ArrayList<ExtIcon>();
100: List<String> names = new ArrayList<String>();
101: for (int i = 0; i < 30; i++) {
102: FileObject prj = TestSupport.createTestProject(workDir,
103: "prj" + i);
104: URL url = URLMapper.findURL(prj, URLMapper.EXTERNAL);
105: list.add(url);
106: names.add(url.toExternalForm());
107: icons.add(new ExtIcon());
108: TestSupport.TestProject tmp = (TestSupport.TestProject) ProjectManager
109: .getDefault().findProject(prj);
110: assertNotNull("Project found", tmp);
111: tmp.setLookup(Lookups.fixed(tmp,
112: new TestProjectOpenedHookImpl(down),
113: new TestSources(tmp)));
114: }
115:
116: OpenProjectListSettings.getInstance().setOpenProjectsURLs(list);
117: OpenProjectListSettings.getInstance()
118: .setOpenProjectsDisplayNames(names);
119: OpenProjectListSettings.getInstance().setOpenProjectsIcons(
120: icons);
121: }
122:
123: @Override
124: protected void tearDown() throws Exception {
125: super .tearDown();
126: }
127:
128: public void testBehaviourOfProjectsLogicNode()
129: throws InterruptedException {
130: Node view = new ProjectsRootNode(ProjectsRootNode.PHYSICAL_VIEW);
131: L listener = new L();
132: view.addNodeListener(listener);
133:
134: assertEquals("30 children", 30, view.getChildren()
135: .getNodesCount());
136: listener.assertEvents("None", 0);
137: assertEquals("No project opened yet", 0,
138: TestProjectOpenedHookImpl.opened);
139:
140: for (Node n : view.getChildren().getNodes()) {
141: TestSupport.TestProject p = n.getLookup().lookup(
142: TestSupport.TestProject.class);
143: assertNull("No project of this type, yet", p);
144: SearchInfo info = n.getLookup().lookup(SearchInfo.class);
145: assertNoRealSearchInfo(n, info);
146: }
147:
148: // let project open code run
149: down.countDown();
150: TestProjectOpenedHookImpl.toOpen.await();
151:
152: assertEquals("All projects opened", 30,
153: TestProjectOpenedHookImpl.opened);
154:
155: OpenProjectList.waitProjectsFullyOpen();
156:
157: Node[] all = view.getChildren().getNodes();
158: assertEquals("3x30", 90, all.length);
159: for (Node n : all) {
160: SearchInfo info = n.getLookup().lookup(SearchInfo.class);
161: assertNoRealSearchInfo(n, info);
162: LogicalView v = n.getLookup().lookup(LogicalView.class);
163: assertEquals("View is not present in physical view", null,
164: v);
165: }
166:
167: // too bad, looks that we need to generate some events
168: //listener.assertEvents("Goal is to receive no events at all", 0);
169: }
170:
171: private static class L implements NodeListener {
172: public List<EventObject> events = new ArrayList<EventObject>();
173:
174: public void childrenAdded(NodeMemberEvent ev) {
175: assertFalse("No event in AWT thread", EventQueue
176: .isDispatchThread());
177: events.add(ev);
178: }
179:
180: public void childrenRemoved(NodeMemberEvent ev) {
181: assertFalse("No event in AWT thread", EventQueue
182: .isDispatchThread());
183: events.add(ev);
184: }
185:
186: public void childrenReordered(NodeReorderEvent ev) {
187: assertFalse("No event in AWT thread", EventQueue
188: .isDispatchThread());
189: events.add(ev);
190: }
191:
192: public void nodeDestroyed(NodeEvent ev) {
193: assertFalse("No event in AWT thread", EventQueue
194: .isDispatchThread());
195: events.add(ev);
196: }
197:
198: public void propertyChange(PropertyChangeEvent evt) {
199: assertFalse("No event in AWT thread", EventQueue
200: .isDispatchThread());
201: events.add(evt);
202: }
203:
204: final void assertEvents(String string, int i) {
205: assertEquals(string + events, i, events.size());
206: events.clear();
207: }
208:
209: }
210:
211: private static class TestProjectOpenedHookImpl extends
212: ProjectOpenedHook {
213:
214: public static CountDownLatch toOpen = new CountDownLatch(30);
215: public static int opened = 0;
216: public static int closed = 0;
217:
218: private CountDownLatch toWaitOn;
219:
220: public TestProjectOpenedHookImpl(CountDownLatch toWaitOn) {
221: this .toWaitOn = toWaitOn;
222: }
223:
224: protected void projectClosed() {
225: closed++;
226: }
227:
228: protected void projectOpened() {
229: if (toWaitOn != null) {
230: try {
231: toWaitOn.await();
232: } catch (InterruptedException ex) {
233: throw new IllegalStateException(ex);
234: }
235: }
236: opened++;
237: toOpen.countDown();
238: }
239:
240: }
241:
242: private static class LVP implements LogicalViewProvider {
243: public Node createLogicalView() {
244: return new LogicalView();
245: }
246:
247: public Node findPath(Node root, Object target) {
248: return null;
249: }
250: }
251:
252: private static class LogicalView extends AbstractNode {
253: public LogicalView() {
254: super (Children.LEAF);
255: }
256: }
257:
258: static void assertNoRealSearchInfo(Node n, SearchInfo info) {
259: if (info != null) {
260: if (info instanceof LazyProject) {
261: // OK
262: } else {
263: fail("No search info at " + n + "\nwas: " + info);
264: }
265: }
266: }
267:
268: private static class TestSources implements Sources {
269: private SourceGroup[] arr;
270:
271: public TestSources(Project p) throws IOException {
272: FileObject internal = FileUtil.createFolder(p
273: .getProjectDirectory(), "src");
274: FileObject external = FileUtil.createFolder(p
275: .getProjectDirectory().getParent(), "src"
276: + p.getProjectDirectory().getNameExt());
277:
278: this .arr = new SourceGroup[] {
279: new TestGroup(p.getProjectDirectory()),
280: new TestGroup(internal), new TestGroup(external), };
281: }
282:
283: public SourceGroup[] getSourceGroups(String type) {
284: return arr;
285: }
286:
287: public void addChangeListener(ChangeListener listener) {
288: }
289:
290: public void removeChangeListener(ChangeListener listener) {
291: }
292: }
293:
294: private static class TestGroup implements SourceGroup {
295: private FileObject root;
296:
297: public TestGroup(FileObject r) {
298: this .root = r;
299: }
300:
301: public FileObject getRootFolder() {
302: return root;
303: }
304:
305: public String getName() {
306: return root.getNameExt();
307: }
308:
309: public String getDisplayName() {
310: return root.getNameExt();
311: }
312:
313: public Icon getIcon(boolean opened) {
314: return null;
315: }
316:
317: public boolean contains(FileObject file)
318: throws IllegalArgumentException {
319: return file.equals(root);
320: }
321:
322: public void addPropertyChangeListener(
323: PropertyChangeListener listener) {
324: }
325:
326: public void removePropertyChangeListener(
327: PropertyChangeListener listener) {
328: }
329: }
330: }
|