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-2008 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.netbeans.modules.url;
043:
044: import java.io.BufferedReader;
045: import java.io.FileNotFoundException;
046: import java.io.IOException;
047: import java.io.InputStream;
048: import java.io.InputStreamReader;
049: import java.io.OutputStream;
050: import java.net.MalformedURLException;
051: import java.net.URL;
052: import org.netbeans.spi.queries.FileEncodingQueryImplementation;
053: import org.openide.DialogDisplayer;
054: import org.openide.cookies.InstanceCookie;
055: import org.openide.cookies.OpenCookie;
056: import org.openide.filesystems.FileLock;
057: import org.openide.filesystems.FileObject;
058: import org.openide.loaders.DataObjectExistsException;
059: import org.openide.loaders.MultiDataObject;
060: import org.openide.loaders.MultiFileLoader;
061: import org.openide.NotifyDescriptor;
062: import org.openide.ErrorManager;
063: import org.openide.util.HelpCtx;
064: import org.openide.util.Lookup;
065: import org.openide.util.NbBundle;
066: import org.openide.util.lookup.Lookups;
067:
068: /** Data object that represents one bookmark, one .url file containing url.
069: *
070: * @author Ian Formanek
071: * @see org.openide.Places.Folders#bookmarks
072: */
073: public class URLDataObject extends MultiDataObject implements
074: OpenCookie, InstanceCookie {
075:
076: /** Name for url property. */
077: static final String PROP_URL = "url"; //NOI18N
078:
079: /** Generated serial version UID. */
080: static final long serialVersionUID = 6829522922370124627L;
081:
082: /** */
083: private Lookup lookup;
084:
085: /**
086: * Constructs a new URL data object.
087: *
088: * @param file file to create an object from
089: * @param loader <code>DataLoader</code> which recognized the file
090: * and initiated calling this constructor
091: */
092: public URLDataObject(final FileObject file, MultiFileLoader loader)
093: throws DataObjectExistsException {
094: super (file, loader);
095: getCookieSet().add(this );
096: }
097:
098: @Override
099: public Lookup getLookup() {
100: if (lookup == null) {
101: FileEncodingQueryImplementation encodingImpl = ((URLDataLoader) getLoader())
102: .getEncoding();
103: lookup = (encodingImpl != null) ? Lookups.fixed(this ,
104: encodingImpl) : Lookups.singleton(this );
105: }
106: return lookup;
107: }
108:
109: /*
110: * PENDING: it would be neat to have get/setURL methods
111: * but, there is a problem(at least at jdk1.3 for linux) with URL.equals
112: * (too much time consuming in underlying native method).
113: */
114:
115: /**
116: * Gets a <code>URL</code> string from the underlying .url file.
117: * The user is notified if an error occures during reading the file.
118: * If there are multiple lines of text in the file, only the first one is
119: * returned and no error is reported.
120: *
121: * @return <code>URL</code> string stored in the file,
122: * an empty string if the file is empty,
123: * or <code>null</code> if an error occured while reading the file
124: */
125: String getURLString() {
126: FileObject urlFile = getPrimaryFile();
127: if (!urlFile.isValid()) {
128: return null;
129: }
130: String urlString = null;
131:
132: InputStream is = null;
133: try {
134: is = urlFile.getInputStream();
135: urlString = new BufferedReader(new InputStreamReader(is))
136: .readLine();
137: } catch (FileNotFoundException fne) {
138: ErrorManager.getDefault().notify(ErrorManager.WARNING, fne);
139: return null;
140: } catch (IOException ioe) {
141: ErrorManager.getDefault().notify(ErrorManager.WARNING, ioe);
142: return null;
143: } finally {
144: if (is != null) {
145: try {
146: is.close();
147: } catch (IOException e) {
148: ErrorManager.getDefault().notify(
149: ErrorManager.INFORMATIONAL, e);
150: }
151: }
152: }
153:
154: if (urlString == null) {
155: /*
156: * If the file is empty, return an empty string.
157: * <null> is reserved for notifications of failures.
158: */
159: urlString = ""; //NOI18N
160: }
161: return urlString;
162: }
163:
164: /**
165: * Stores a specified URL into the file backing up this URL object.
166: *
167: * @param newUrlString URL to be stored in the file
168: */
169: void setURLString(String newUrlString) {
170: FileObject urlFile = getPrimaryFile();
171: if (!urlFile.isValid()) {
172: return;
173: }
174: FileLock lock = null;
175: try {
176: lock = urlFile.lock();
177: OutputStream os = urlFile.getOutputStream(lock);
178: os.write(newUrlString.getBytes());
179: os.close();
180: } catch (IOException ioe) {
181: ErrorManager.getDefault().notify(ErrorManager.WARNING, ioe);
182: } finally {
183: if (lock != null) {
184: lock.releaseLock();
185: }
186: }
187: }
188:
189: /** */
190: @Override
191: public HelpCtx getHelpCtx() {
192: return new HelpCtx(URLDataObject.class);
193: }
194:
195: /* implements interface OpenCookie */
196: public void open() {
197: String urlString = getURLString();
198: if (urlString == null) {
199: return;
200: }
201: URL url = getURLFromString(urlString);
202: if (url == null) {
203: return;
204: }
205: org.openide.awt.HtmlBrowser.URLDisplayer.getDefault().showURL(
206: url);
207: }
208:
209: /**
210: * Converts an URL string to an <code>URL</code> object.
211: * Notifies the user in case of failure.
212: *
213: * @param urlString string to convert to <code>URL</code>
214: * @return <code>URL</code> object representing the specified URL;
215: * or <code>null</code> in case of failure
216: */
217: private static URL getURLFromString(String urlString) {
218: try {
219: return new URL(urlString);
220: } catch (MalformedURLException mue1) {
221: }
222:
223: /* failed - try to prepend 'http://' */
224: try {
225: return new URL("http://" + urlString); //NOI18N
226: } catch (MalformedURLException mue1) {
227: }
228:
229: /* failed again - notify about the failure and return null: */
230: String msg;
231: if (urlString.length() > 50) { //too long URL
232: msg = NbBundle.getMessage(URLDataObject.class,
233: "MSG_MalformedURLError"); //NOI18N
234: } else {
235: msg = NbBundle.getMessage(URLDataObject.class,
236: "MSG_FMT_MalformedURLError", //NOI18N
237: urlString);
238: }
239: DialogDisplayer.getDefault().notify(
240: new NotifyDescriptor.Message(msg,
241: NotifyDescriptor.ERROR_MESSAGE));
242: return null;
243: }
244:
245: /* implements interface InstanceCookie */
246: public String instanceName() {
247: return getName();
248: }
249:
250: /* implements interface InstanceCookie */
251: /**
252: * @return class <code>URLPresenter</code>
253: * @see URLPresenter
254: */
255: public Class instanceClass() throws IOException,
256: ClassNotFoundException {
257: return URLPresenter.class;
258: }
259:
260: /* implements interface InstanceCookie */
261: /**
262: * Creates an instance of <code>URLPresenter</code>.
263: *
264: * @return instance of class <code>URLPresenter</code>
265: * @see URLPresenter
266: */
267: public Object instanceCreate() throws IOException,
268: ClassNotFoundException {
269: return new URLPresenter(this);
270: }
271:
272: }
|