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-2007 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:
042: package org.openide.loaders;
043:
044: import java.io.IOException;
045: import java.io.InputStream;
046: import java.util.ArrayList;
047: import java.util.HashSet;
048: import java.util.List;
049: import java.util.logging.Level;
050: import org.openide.DialogDisplayer;
051: import org.openide.NotifyDescriptor;
052: import org.openide.cookies.CloseCookie;
053: import org.openide.cookies.EditCookie;
054: import org.openide.cookies.EditorCookie;
055: import org.openide.cookies.OpenCookie;
056: import org.openide.cookies.PrintCookie;
057: import org.openide.filesystems.FileLock;
058: import org.openide.filesystems.FileObject;
059: import org.openide.util.HelpCtx;
060: import org.openide.util.NbBundle;
061: import org.openide.nodes.Node;
062: import org.openide.util.Lookup;
063:
064: /** An implementation of a data object which consumes file objects not recognized by any other loaders.
065: */
066: final class DefaultDataObject extends MultiDataObject implements
067: OpenCookie {
068: static final long serialVersionUID = -4936309935667095746L;
069: /** editor for default editor support */
070: private DefaultES support;
071:
072: /** generated Serialized Version UID */
073: // static final long serialVersionUID = 6305590675982925167L;
074: /** Constructs new data shadow for given primary file and referenced original.
075: * @param fo the primary file
076: * @param original original data object
077: */
078: DefaultDataObject(FileObject fo, MultiFileLoader loader)
079: throws DataObjectExistsException {
080: super (fo, loader);
081: }
082:
083: /* Creates node delegate.
084: */
085: @Override
086: protected Node createNodeDelegate() {
087: DataNode dn = new DataNode(this ,
088: org.openide.nodes.Children.LEAF);
089:
090: // netbeans.core.nodes.description
091: dn.setShortDescription(NbBundle.getMessage(
092: DefaultDataObject.class, "HINT_DefaultDataObject")); // NOI18N
093: return dn;
094: }
095:
096: /** Get the name of the data object.
097: * <p>The implementation uses the name of the primary file and its exten.
098: * @return the name
099: */
100:
101: @Override
102: public String getName() {
103: return getPrimaryFile().getNameExt();
104: }
105:
106: /* Help context for this object.
107: * @return help context
108: */
109: @Override
110: public HelpCtx getHelpCtx() {
111: return HelpCtx.DEFAULT_HELP;
112: }
113:
114: /* Handles renaming of the object.
115: * Must be overriden in children.
116: *
117: * @param name name to rename the object to
118: * @return new primary file of the object
119: * @exception IOException if an error occures
120: */
121: @Override
122: protected FileObject handleRename(String name) throws IOException {
123: FileLock lock = getPrimaryFile().lock();
124: int pos = name.lastIndexOf('.');
125:
126: try {
127: if (pos < 0) {
128: // file without separator
129: getPrimaryFile().rename(lock, name, null);
130: } else if (pos == 0) {
131: getPrimaryFile().rename(lock, name,
132: getPrimaryFile().getExt());
133: } else {
134: if (!name.equals(getPrimaryFile().getNameExt())) {
135: getPrimaryFile().rename(lock,
136: name.substring(0, pos),
137: name.substring(pos + 1, name.length()));
138: DataObjectPool
139: .getPOOL()
140: .revalidate(
141: new HashSet<FileObject>(
142: java.util.Collections
143: .singleton(getPrimaryFile())));
144: }
145: }
146: } finally {
147: lock.releaseLock();
148: }
149: return getPrimaryFile();
150: }
151:
152: /* Creates new object from template.
153: * @exception IOException
154: */
155: @Override
156: protected DataObject handleCreateFromTemplate(DataFolder df,
157: String name) throws IOException {
158: // avoid doubling of extension
159: if (name != null
160: && name.endsWith("." + getPrimaryFile().getExt())) {
161: // NOI18N
162: name = name.substring(0, name.lastIndexOf("."
163: + getPrimaryFile().getExt())); // NOI18N
164: } // NOI18N
165:
166: return super .handleCreateFromTemplate(df, name);
167: }
168:
169: @Override
170: protected DataObject handleCopyRename(DataFolder df, String name,
171: String ext) throws IOException {
172: FileObject fo = getPrimaryEntry().copyRename(
173: df.getPrimaryFile(), name, ext);
174: return DataObject.find(fo);
175: }
176:
177: /** Either opens the in text editor or asks user questions.
178: */
179: public void open() {
180: EditorCookie ic = getCookie(EditorCookie.class);
181: if (ic != null) {
182: ic.open();
183: } else {
184: // ask a query
185: List<Object> options = new ArrayList<Object>();
186: options.add(NotifyDescriptor.OK_OPTION);
187: options.add(NotifyDescriptor.CANCEL_OPTION);
188: NotifyDescriptor nd = new NotifyDescriptor(NbBundle
189: .getMessage(DefaultDataObject.class,
190: "MSG_BinaryFileQuestion"), NbBundle
191: .getMessage(DefaultDataObject.class,
192: "MSG_BinaryFileWarning"),
193: NotifyDescriptor.DEFAULT_OPTION,
194: NotifyDescriptor.QUESTION_MESSAGE, options
195: .toArray(), null);
196: Object ret = DialogDisplayer.getDefault().notify(nd);
197: if (ret != NotifyDescriptor.OK_OPTION) {
198: return;
199: }
200:
201: EditorCookie c = getCookie(EditorCookie.class, true);
202: c.open();
203: }
204: }
205:
206: @Override
207: public Lookup getLookup() {
208: return getCookieSet().getLookup();
209: }
210:
211: /** We implement OpenCookie and sometimes we also have cloneable
212: * editor cookie */
213: @Override
214: public <T extends Node.Cookie> T getCookie(Class<T> c) {
215: return getCookie(c, false);
216: }
217:
218: @Override
219: final void checkCookieSet(Class<?> c) {
220: if (Node.Cookie.class.isAssignableFrom(c) && support == null) {
221: Class<? extends Node.Cookie> cookie = c
222: .asSubclass(Node.Cookie.class);
223: fixCookieSet(cookie, false);
224: }
225: }
226:
227: /** Getter for cookie.
228: * @param force if true, there are no checks for content of the file
229: */
230: final <T extends Node.Cookie> T getCookie(Class<T> c, boolean force) {
231: if (c == OpenCookie.class) {
232: return c.cast(this );
233: }
234:
235: T cook = super .getCookie(c);
236: if (cook != null) {
237: return cook;
238: }
239: fixCookieSet(c, force);
240: return getCookieSet().getCookie(c);
241: }
242:
243: private void fixCookieSet(Class<?> c, boolean force) {
244: if (support != null) {
245: return;
246: }
247:
248: if (c.isAssignableFrom(EditCookie.class)
249: || c.isAssignableFrom(EditorCookie.Observable.class)
250: || c.isAssignableFrom(PrintCookie.class)
251: || c.isAssignableFrom(CloseCookie.class)
252: || c == DefaultES.class) {
253: try {
254: if (!force) {
255: // try to initialize the editor cookie set if the file
256: // seems editable
257: byte[] arr = new byte[2048];
258: InputStream is = getPrimaryFile().getInputStream();
259: try {
260: int len = is.read(arr);
261: for (int i = 0; i < len; i++) {
262: if (arr[i] >= 0 && arr[i] <= 31
263: && arr[i] != '\n' && arr[i] != '\r'
264: && arr[i] != '\t') {
265: return;
266: }
267: }
268: } finally {
269: is.close();
270: }
271: }
272: support = new DefaultES(this , getPrimaryEntry(),
273: getCookieSet());
274: getCookieSet().assign(DefaultES.class, support);
275: } catch (IOException ex) {
276: LOG.log(Level.INFO, "Cannot read " + getPrimaryEntry(),
277: ex); // NOI18N
278: }
279: }
280: }
281: }
|