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: * Portions Copyrighted 2007 Sun Microsystems, Inc.
027: */
028: package org.netbeans.modules.visualweb.project.jsfloader;
029:
030: import java.io.IOException;
031: import java.lang.ref.WeakReference;
032: import java.net.MalformedURLException;
033: import java.net.URL;
034: import java.util.HashMap;
035: import java.util.WeakHashMap;
036: import javax.swing.Action;
037: import javax.swing.JComponent;
038: import org.netbeans.api.project.FileOwnerQuery;
039: import org.netbeans.api.project.Project;
040: import org.netbeans.core.spi.multiview.CloseOperationState;
041: import org.netbeans.core.spi.multiview.MultiViewElement;
042: import org.netbeans.core.spi.multiview.MultiViewElementCallback;
043: import org.netbeans.spi.project.AuxiliaryConfiguration;
044: import org.netbeans.spi.project.LookupProvider;
045: import org.netbeans.spi.project.ui.ProjectOpenedHook;
046: import org.openide.awt.UndoRedo;
047: import org.openide.filesystems.FileObject;
048: import org.openide.filesystems.URLMapper;
049: import org.openide.loaders.DataObject;
050: import org.openide.util.Lookup;
051: import org.openide.util.lookup.Lookups;
052: import org.w3c.dom.Element;
053: import org.w3c.dom.NodeList;
054:
055: /**
056: * Workaround for http://www.netbeans.org/issues/show_bug.cgi?id=58136. Saves the
057: * currently selected tab for JSF multiviews that are still opened when a project is closed.
058: *
059: * @author quynguyen
060: */
061: public final class OpenEditOverride implements LookupProvider {
062: // Taken from org.netbeans.modules.project.ui.ProjectUtilities
063: private static final String OPEN_FILES_NS = "http://www.netbeans.org/ns/projectui-open-files/1"; // NOI18N
064: private static final String OPEN_FILES_ELEMENT = "open-files"; // NOI18N
065: private static final String FILE_ELEMENT = "file"; // NOI18N
066:
067: static final String MULTIVIEW_ATTRIBUTE = "selected-multiview";
068:
069: private static WeakHashMap<Project, HashMap<FileObject, String>> multiViewsByProject = new WeakHashMap<Project, HashMap<FileObject, String>>();
070:
071: public Lookup createAdditionalLookup(Lookup baseContext) {
072: Project proj = baseContext.lookup(Project.class);
073: return Lookups.singleton(new ProjectOpenedHookImpl(proj));
074: }
075:
076: private static void multiViewChanged(Project fromProject,
077: DataObject multiViewDO, String multiViewId) {
078: HashMap<FileObject, String> projectMultiViews = multiViewsByProject
079: .get(fromProject);
080:
081: if (projectMultiViews == null) {
082: projectMultiViews = new HashMap<FileObject, String>();
083: multiViewsByProject.put(fromProject, projectMultiViews);
084: }
085: projectMultiViews
086: .put(multiViewDO.getPrimaryFile(), multiViewId);
087: }
088:
089: private static void unregisterProject(Project proj) {
090: multiViewsByProject.remove(proj);
091: }
092:
093: private static final class ProjectOpenedHookImpl extends
094: ProjectOpenedHook {
095: private WeakReference<Project> projectRef;
096:
097: public ProjectOpenedHookImpl(Project project) {
098: this .projectRef = new WeakReference<Project>(project);
099: }
100:
101: @Override
102: protected void projectOpened() {
103: // NO-OP
104: }
105:
106: @Override
107: protected void projectClosed() {
108: Project project = projectRef.get();
109: if (project != null) {
110: AuxiliaryConfiguration aux = project.getLookup()
111: .lookup(AuxiliaryConfiguration.class);
112: HashMap<FileObject, String> multiviews = multiViewsByProject
113: .get(project);
114: multiviews = (multiviews == null) ? new HashMap<FileObject, String>(
115: 1)
116: : multiviews;
117:
118: if (aux != null) {
119: Element openFiles = aux.getConfigurationFragment(
120: OPEN_FILES_ELEMENT, OPEN_FILES_NS, false);
121:
122: if (openFiles == null)
123: return;
124:
125: NodeList fileNodeList = openFiles
126: .getElementsByTagName(FILE_ELEMENT);
127: for (int i = 0; i < fileNodeList.getLength(); i++) {
128: String url = fileNodeList.item(i)
129: .getChildNodes().item(0).getNodeValue();
130: FileObject fo;
131: try {
132: fo = URLMapper.findFileObject(new URL(url));
133: } catch (MalformedURLException mue) {
134: assert false : "MalformedURLException in "
135: + url;
136: continue;
137: }
138: if (fo == null) {
139: continue;
140: }
141:
142: if (FileOwnerQuery.getOwner(fo) != project) {
143: continue;
144: }
145:
146: try {
147: DataObject dobj = DataObject.find(fo);
148: if (dobj instanceof JsfJspDataObject) {
149: FileObject primaryFile = dobj
150: .getPrimaryFile();
151: String mvId = multiviews
152: .get(primaryFile);
153:
154: primaryFile.setAttribute(
155: MULTIVIEW_ATTRIBUTE, mvId);
156: }
157: } catch (IOException ex) {
158: assert false : "IOException for FileObject: "
159: + fo.getPath();
160: continue;
161: }
162: }
163: }
164:
165: unregisterProject(project);
166: }
167: }
168: }
169:
170: static final class MultiViewDelegate implements MultiViewElement {
171: private final MultiViewElement originalElement;
172: private final String mvIdentifier;
173: private final DataObject dobj;
174: private WeakReference<Project> associatedProject;
175:
176: public MultiViewDelegate(MultiViewElement originalElement,
177: String mvIdentifier, DataObject dobj) {
178: this .originalElement = originalElement;
179: this .mvIdentifier = mvIdentifier;
180: this .dobj = dobj;
181:
182: associatedProject = new WeakReference<Project>(
183: FileOwnerQuery.getOwner(dobj.getPrimaryFile()));
184: }
185:
186: public MultiViewElement getOriginal() {
187: return originalElement;
188: }
189:
190: public void componentShowing() {
191: Project projectRef = associatedProject.get();
192: if (projectRef != null) {
193: multiViewChanged(projectRef, dobj, mvIdentifier);
194: }
195:
196: originalElement.componentShowing();
197: }
198:
199: //// MultiViewElement implementation
200: public JComponent getVisualRepresentation() {
201: return originalElement.getVisualRepresentation();
202: }
203:
204: public JComponent getToolbarRepresentation() {
205: return originalElement.getToolbarRepresentation();
206: }
207:
208: public Action[] getActions() {
209: return originalElement.getActions();
210: }
211:
212: public Lookup getLookup() {
213: return originalElement.getLookup();
214: }
215:
216: public void componentOpened() {
217: originalElement.componentOpened();
218: }
219:
220: public void componentClosed() {
221: originalElement.componentClosed();
222: }
223:
224: public void componentHidden() {
225: originalElement.componentHidden();
226: }
227:
228: public void componentActivated() {
229: originalElement.componentActivated();
230: }
231:
232: public void componentDeactivated() {
233: originalElement.componentDeactivated();
234: }
235:
236: public UndoRedo getUndoRedo() {
237: return originalElement.getUndoRedo();
238: }
239:
240: public void setMultiViewCallback(
241: MultiViewElementCallback callback) {
242: originalElement.setMultiViewCallback(callback);
243: }
244:
245: public CloseOperationState canCloseElement() {
246: return originalElement.canCloseElement();
247: }
248:
249: }
250: }
|