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:
042: package org.netbeans.jellytools.util;
043:
044: import java.io.*;
045: import java.net.MalformedURLException;
046: import java.net.URL;
047: import org.netbeans.jellytools.JellyTestCase;
048: import org.netbeans.jellytools.nodes.Node;
049: import org.netbeans.jemmy.JemmyException;
050: import org.netbeans.jemmy.operators.JTreeOperator;
051: import org.openide.ErrorManager;
052: import org.openide.filesystems.*;
053: import org.openide.filesystems.FileSystem.AtomicAction;
054: import org.openide.loaders.DataObject;
055: import org.openide.loaders.DataObjectNotFoundException;
056:
057: /**
058: * The FolderContext class contains methods for finding, creating, removing Data
059: * Objects, File Objects and Nodes in a given folder (e.g. 'data'). All objects
060: * are addresed relatively to the folder.
061: * <p>
062: * Usage:<br>
063: * <pre>
064: * public class TestTest extends JellyTestCase {
065: * ...
066: * public void test() throws Exception {
067: * // find data folder
068: * FolderContext df = FolderContext.getDataFolder(this);
069: * // create folder
070: * df.createFolder("resources");
071: * // create file with given content
072: * DataObject bundle = df.createDataObject("resources/Bundle.properties", "OpenIDE-Module-Name=My Module\n");
073: * // new from template
074: * NewWizardOperator.create("Java Package", df.getTreePath("resources"), "org.netbeans.modules");
075: * Node node = df.getJellyNode("resources|Bundle");
076: * ...
077: * // remove garbage
078: * df.deleteDataObject("resources");
079: * ...
080: * // find work dir, create and mount it if necesarry
081: * FolderContext wd = FolderContext.getWorkDir(this);
082: * ...
083: * </pre>
084: *
085: * @author ms113234
086: */
087: public class FolderContext {
088: private URL _base;
089:
090: /** Creates a new instance of FolderContext.
091: * @param url folder's URL
092: */
093: @SuppressWarnings("deprecation")
094: public FolderContext(URL url) {
095: FileObject[] fos = URLMapper.findFileObjects(url);
096: if (fos == null || fos.length == 0) {
097: throw new IllegalStateException("Cannot find file object: "
098: + url);
099: }
100: _base = url;
101: }
102:
103: /** Returns data folder context for given test.
104: * @param test the test
105: * @return FolderContext
106: */
107: public static FolderContext getDataFolder(JellyTestCase test) {
108: URL url = test.getClass().getResource("data/");
109: if (url == null) {
110: throw new IllegalStateException(
111: "Cannot find 'data' folder for: "
112: + test.getClass().getName());
113: }
114: return new FolderContext(url);
115: }
116:
117: /** Returns working directory context for given test. If working directory
118: * is not available method tries to creat it.
119: * @param test the test
120: * @throws IOException if the directory cannot be created
121: * @return FolderContext
122: */
123: @SuppressWarnings("deprecation")
124: public static FolderContext getWorkDir(JellyTestCase test)
125: throws IOException {
126: String wd = test.getWorkDir().getAbsolutePath();
127: FileSystem fs = Repository.getDefault().findFileSystem(wd);
128: /* RepositoryTabOperator removed from jellytools
129: if (fs == null) {
130: RepositoryTabOperator.invoke().mountLocalDirectoryAPI(wd);
131: }
132: fs = Repository.getDefault().findFileSystem(wd);
133: */
134: if (fs == null) {
135: throw new IllegalStateException("Cannot mount: " + wd);
136: }
137: URL url = fs.getRoot().getURL();
138: if (url == null) {
139: throw new IllegalStateException(
140: "Cannot find work dir for: "
141: + test.getClass().getName());
142: }
143: return new FolderContext(url);
144: }
145:
146: /** Finds the File Object. The spec is
147: * a "/" separated relative path that identifies the File Object.
148: * @param spec File Object's path
149: * @return FileObject
150: */
151: @SuppressWarnings("deprecation")
152: public FileObject getFileObject(String spec) {
153: FileObject fo = null;
154: URL url = null;
155: if (spec == null) {
156: url = _base;
157: } else {
158: url = makeURL(spec);
159: }
160: FileObject[] fos = URLMapper.findFileObjects(url);
161: if (fos == null || fos.length == 0) {
162: return null;
163: } else {
164: return fos[0];
165: }
166: }
167:
168: /** Creates folder.
169: * @param spec folder's relative path separated by '/'
170: * @throws IOException if the folder cannot be created
171: * @return DataObject
172: */
173: public DataObject createFolder(String spec) throws IOException {
174: return createDataObject(spec, null);
175: }
176:
177: /** Creates Data Object.
178: * @param spec Data Object's relative path separated by '/'
179: * @param content Data Object's content
180: * @throws IOException if the Data Object cannot be created
181: * @return DataObject
182: */
183: public DataObject createDataObject(String spec, final String content)
184: throws IOException {
185: File file = new File(spec);
186: final String path = file.getParent();
187: final String name = file.getName();
188:
189: final FileObject parent = getFileObject(path);
190: if (parent == null) {
191: throw new IllegalStateException("Cannot find folder: "
192: + makeURL(path));
193: }
194: FileSystem filesystem = parent.getFileSystem();
195:
196: final FileObject[] fileObject = new FileObject[1];
197: AtomicAction fsAction = new AtomicAction() {
198: public void run() throws IOException {
199: if (content == null) {
200: // create folder
201: fileObject[0] = parent.createFolder(name);
202: } else {
203: // create file
204: FileObject fo = parent.createData(name);
205: FileLock lock = null;
206: try {
207: lock = fo.lock();
208: OutputStream out = fo.getOutputStream(lock);
209: out = new BufferedOutputStream(out);
210: Writer writer = new OutputStreamWriter(out,
211: "UTF8");
212: writer.write(content);
213: writer.close();
214: // return DataObject
215: lock.releaseLock();
216: lock = null;
217: fileObject[0] = fo;
218: } finally {
219: if (lock != null)
220: lock.releaseLock();
221: }
222: }
223: }
224: };
225:
226: filesystem.runAtomicAction(fsAction);
227: return DataObject.find(fileObject[0]);
228: }
229:
230: /** Finds the Data Object. The spec is
231: * a "/" separated relative path that identifies the Data Object.
232: * @return Data Object or 'null' if the Data Object does not exist
233: * @param spec Data Object's path
234: */
235: public DataObject getDataObject(String spec) {
236: DataObject dto = null;
237: FileObject fo = getFileObject(spec);
238: if (fo != null) {
239: try {
240: dto = DataObject.find(fo);
241: } catch (DataObjectNotFoundException nfe) {
242: /* dto = null; */
243: }
244: }
245: return dto;
246: }
247:
248: /** Deletes the File Object. The spec is
249: * a "/" separated relative path that identifies the File Object.
250: * @param spec File Object's path
251: * @throws IOException if something fails
252: */
253: public void deleteDataObject(String spec) throws IOException {
254: DataObject dataObject = getDataObject(spec);
255: if (dataObject == null) {
256: // nothing to delete
257: return;
258: }
259: dataObject.getNodeDelegate().destroy();
260: }
261:
262: /** Finds Jelly Node.
263: * @param path Jelly Node's relative path separated by '|'
264: * @return Node
265: */
266: /* RepositoryTabOperator removed from jellytools
267: public Node getJellyNode(String path) {
268: Node node = null;
269: String treePath = getTreePath(path) ;
270: JTreeOperator tree = RepositoryTabOperator.invoke().tree();
271: node = new Node(tree, treePath);
272: return node;
273: }
274: */
275:
276: /** Returns absolute Tree Path.
277: * @param path relative path separated by '|'
278: * @return String
279: */
280: @SuppressWarnings("deprecation")
281: public String getTreePath(String path) {
282: String tp = null;
283: FileObject fo = getFileObject("");
284: try {
285: tp = fo.getFileSystem().getDisplayName() + '|'
286: + fo.getPackageName('|') + '|' + path;
287: } catch (FileStateInvalidException fsie) {
288: throw new JemmyException("Cannot get filesystem for: "
289: + fo.getPackageNameExt('/', '.'), fsie);
290: }
291: return tp;
292: }
293:
294: // LIB /////////////////////////////////////////////////////////////////////
295:
296: /** Creates URL from _base context and relative identifier 'spec' */
297: private URL makeURL(String spec) {
298: if (spec == null || spec.equals("")) {
299: return _base;
300: }
301: // Emits leading whitespaces and '/'.
302: spec.trim();
303: while (spec.startsWith("/")) {
304: spec = spec.substring(1);
305: }
306: URL url = _base;
307: try {
308: url = new URL(_base, spec);
309: } catch (MalformedURLException mue) { /* url = _base; */
310: }
311: return url;
312: }
313: }
|