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: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.subversion.ui.checkout;
042:
043: import org.netbeans.api.project.Project;
044: import org.netbeans.api.project.ProjectUtils;
045: import org.netbeans.api.project.ProjectManager;
046: import org.netbeans.spi.project.ui.support.CommonProjectActions;
047: import org.netbeans.spi.project.ui.support.ProjectChooser;
048: import org.openide.filesystems.FileUtil;
049: import org.openide.nodes.Node;
050: import org.openide.explorer.ExplorerManager;
051: import org.openide.windows.TopComponent;
052: import org.openide.windows.WindowManager;
053: import org.openide.filesystems.FileObject;
054:
055: import javax.swing.*;
056: import java.awt.event.ActionEvent;
057: import java.util.List;
058: import java.util.LinkedList;
059: import java.util.Enumeration;
060: import java.util.Collections;
061: import java.io.IOException;
062: import java.io.File;
063: import java.util.logging.Level;
064: import org.netbeans.modules.subversion.Subversion;
065: import org.openide.nodes.Children;
066:
067: /**
068: * Simpliied nb_all/projects/projectui/src/org/netbeans/modules/project/ui/ProjectUtilities.java,
069: * nb_all/projects/projectui/src/org/netbeans/modules/project/ui/ProjectTab.java and
070: * nb_all/ide/welcome/src/org/netbeans/modules/welcome/ui/TitlePanel.java copy.
071: *
072: * @author Petr Kuzel
073: */
074: final class ProjectUtilities {
075:
076: private static final String ProjectTab_ID_LOGICAL = "projectTabLogical_tc"; // NOI18N
077:
078: public static void selectAndExpandProject(final Project project) {
079:
080: // invoke later to select the being opened project if the focus is outside ProjectTab
081: SwingUtilities.invokeLater(new Runnable() {
082:
083: final ExplorerManager.Provider ptLogial = findDefault(ProjectTab_ID_LOGICAL);
084:
085: public void run() {
086: Node root = ptLogial.getExplorerManager()
087: .getRootContext();
088: for (Node projNode : root.getChildren().getNodes()) {
089: Project p = (Project) projNode.getLookup().lookup(
090: Project.class);
091: if (p != null
092: && p.getProjectDirectory().equals(
093: project.getProjectDirectory())) {
094: try {
095: ptLogial.getExplorerManager()
096: .setSelectedNodes(
097: new Node[] { projNode });
098: } catch (Exception ignore) {
099: // may ignore it
100: }
101: }
102: }
103: }
104: });
105: }
106:
107: /* Singleton accessor. As ProjectTab is persistent singleton this
108: * accessor makes sure that ProjectTab is deserialized by window system.
109: * Uses known unique TopComponent ID TC_ID = "projectTab_tc" to get ProjectTab instance
110: * from window system. "projectTab_tc" is name of settings file defined in module layer.
111: * For example ProjectTabAction uses this method to create instance if necessary.
112: */
113: private static synchronized ExplorerManager.Provider findDefault(
114: String tcID) {
115: TopComponent tc = WindowManager.getDefault().findTopComponent(
116: tcID);
117: return (ExplorerManager.Provider) tc;
118: }
119:
120: /**
121: * Runs <i>New Project...</i> wizard with redefined defaults:
122: * <ul>
123: * <li>default project directory to working folder to
124: * capture creating new project in placeholder
125: * directory prepared by CVS server admin
126: * <li>CommonProjectActions.EXISTING_SOURCES_FOLDER
127: * pointing to working folder to capture
128: * typical <i>... from Existing Sources</i> panel
129: * <i>Add</i> button behaviour.
130: * </ul>
131: */
132: public static void newProjectWizard(File workingDirectory) {
133: Action action = CommonProjectActions.newProjectAction();
134: if (action != null) {
135: File original = ProjectChooser.getProjectsFolder();
136: ProjectChooser.setProjectsFolder(workingDirectory);
137: FileObject workingFolder = FileUtil
138: .toFileObject(workingDirectory);
139: action.putValue(
140: CommonProjectActions.EXISTING_SOURCES_FOLDER,
141: workingFolder);
142: performAction(action);
143: try {
144: ProjectChooser.setProjectsFolder(original);
145: } catch (IllegalArgumentException e) {
146: // it seems the original folder is invalid, ignore this
147: }
148: }
149: }
150:
151: /**
152: * Scans given folder (and subfolder into deep 5) for projects.
153: * @return List of {@link Project}s never <code>null</code>.
154: */
155: public static List<Project> scanForProjects(FileObject scanRoot) {
156: ProjectManager.getDefault().clearNonProjectCache();
157: return scanForProjectsRecursively(scanRoot, 5);
158: }
159:
160: private static List<Project> scanForProjectsRecursively(
161: FileObject scanRoot, int deep) {
162: if (deep <= 0)
163: return Collections.emptyList();
164: List<Project> projects = new LinkedList<Project>();
165: ProjectManager projectManager = ProjectManager.getDefault();
166: if (scanRoot.isFolder() && projectManager.isProject(scanRoot)) {
167: try {
168: Project prj = projectManager.findProject(scanRoot);
169: if (prj != null) {
170: projects.add(prj);
171: }
172: } catch (IOException e) {
173: // it happens for all apisupport projects unless
174: // checked out into directory that contains nbbuild and openide folders
175: // apisupport project is valid only if placed in defined directory structure
176: Subversion.LOG.log(Level.INFO,
177: " ignoring suspicious project folder...", e); // NOI18N
178: }
179: }
180: Enumeration en = scanRoot.getChildren(false);
181: while (en.hasMoreElements()) {
182: FileObject fo = (FileObject) en.nextElement();
183: if (fo.isFolder()) {
184: List<Project> nested = scanForProjectsRecursively(fo,
185: deep - 1); // RECURSION
186: projects.addAll(nested);
187: }
188: }
189: return projects;
190: }
191:
192: private static boolean performAction(Action a) {
193: if (a == null) {
194: return false;
195: }
196: ActionEvent ae = new ActionEvent(ProjectUtilities.class,
197: ActionEvent.ACTION_PERFORMED, "command"); // NOI18N
198: try {
199: a.actionPerformed(ae);
200: return true;
201: } catch (Exception e) {
202: Subversion.LOG.log(Level.WARNING, null, e);
203: return false;
204: }
205: }
206:
207: }
|