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.openide.loaders;
043:
044: import java.beans.PropertyChangeEvent;
045: import java.beans.PropertyChangeListener;
046: import org.openide.cookies.OpenCookie;
047:
048: import org.openide.filesystems.*;
049: import org.netbeans.junit.*;
050: import java.io.IOException;
051: import java.util.*;
052: import java.util.logging.Level;
053: import org.openide.*;
054: import org.openide.util.Enumerations;
055:
056: /**
057: * @author Jaroslav Tulach
058: */
059: public class MultiDataObjectTest extends NbTestCase {
060: FileSystem fs;
061: DataObject one;
062: DataFolder from;
063: DataFolder to;
064: ErrorManager err;
065:
066: /** Creates new DataObjectTest */
067: public MultiDataObjectTest(String name) {
068: super (name);
069: }
070:
071: protected Level logLevel() {
072: return Level.INFO;
073: }
074:
075: public void setUp() throws Exception {
076: clearWorkDir();
077:
078: super .setUp();
079:
080: MockServices.setServices(Pool.class);
081:
082: err = ErrorManager.getDefault()
083: .getInstance("TEST-" + getName());
084:
085: LocalFileSystem lfs = new LocalFileSystem();
086: lfs.setRootDirectory(getWorkDir());
087: fs = lfs;
088: FileUtil.createData(fs.getRoot(), "from/x.prima");
089: FileUtil.createData(fs.getRoot(), "from/x.seconda");
090: FileUtil.createFolder(fs.getRoot(), "to/");
091:
092: one = DataObject.find(fs.findResource("from/x.prima"));
093: assertEquals(SimpleObject.class, one.getClass());
094:
095: from = one.getFolder();
096: to = DataFolder.findFolder(fs.findResource("to/"));
097:
098: assertEquals("Nothing there", 0, to.getPrimaryFile()
099: .getChildren().length);
100: }
101:
102: public void testTheSetOfSecondaryEntriesIsSaidToGetInconsistent()
103: throws Exception {
104: for (int i = 0; i < 10; i++) {
105: err.log(i + " getting children of to");
106: DataObject[] to1 = to.getChildren();
107: err.log(i + " getting children of from");
108: DataObject[] from1 = from.getChildren();
109: err.log(i + " getting files of object1");
110: Object[] arr1 = one.files().toArray();
111: err.log(i + " moving the object");
112: one.move(to);
113: err.log(i + " 2nd children of to");
114: DataObject[] to2 = to.getChildren();
115: err.log(i + " 2nd children of from");
116: DataObject[] from2 = from.getChildren();
117: err.log(i + " 2nd files of object1");
118: Object[] arr2 = one.files().toArray();
119: err.log(i + " checking results");
120:
121: assertEquals("Round " + i + " To is empty: "
122: + Arrays.asList(to1), 0, to1.length);
123: assertEquals("Round " + i + " From has one:"
124: + Arrays.asList(from1), 1, from1.length);
125: assertEquals("Round " + i + " One has two files"
126: + Arrays.asList(arr1), 2, arr1.length);
127:
128: assertEquals("Round " + i + " From is empty after move: "
129: + Arrays.asList(from2), 0, from2.length);
130: assertEquals("Round " + i + " To has one:"
131: + Arrays.asList(to2), 1, to2.length);
132: assertEquals("Round " + i + " One still has two files"
133: + Arrays.asList(arr1), 2, arr1.length);
134:
135: err.log(i + " moving back");
136: one.move(from);
137: err.log(i + " end of cycle");
138: }
139: }
140:
141: public void testConsistencyWithABitOfAsynchronicity()
142: throws Exception {
143: err.log(" getting children of to");
144: DataObject[] to1 = to.getChildren();
145: err.log(" getting children of from");
146: DataObject[] from1 = from.getChildren();
147:
148: for (int i = 0; i < 10; i++) {
149: err.log(i + " getting files of object1");
150: Object[] arr1 = one.files().toArray();
151: err.log(i + " moving the object");
152: one.move(to);
153: Object[] arr2 = one.files().toArray();
154: err.log(i + " checking results");
155:
156: assertEquals("Round " + i + " One has two files"
157: + Arrays.asList(arr1), 2, arr1.length);
158:
159: assertEquals("Round " + i + " One still has two files"
160: + Arrays.asList(arr1), 2, arr1.length);
161:
162: err.log(i + " moving back");
163: one.move(from);
164: err.log(i + " end of cycle");
165: }
166: }
167:
168: public void testConsistencyWithABitOfAsynchronicityAndNoObservationsThatWouldMangeTheState()
169: throws Exception {
170: err.log(" getting children of to");
171: DataObject[] to1 = to.getChildren();
172: err.log(" getting children of from");
173: DataObject[] from1 = from.getChildren();
174:
175: for (int i = 0; i < 10; i++) {
176: err.log(i + " moving the object");
177: one.move(to);
178: err.log(i + " moving back");
179: one.move(from);
180: err.log(i + " end of cycle");
181: }
182: }
183:
184: public void testConsistencyWithContinuousQueryingForDeletedFiles()
185: throws Exception {
186: err.log(" getting children of to");
187: DataObject[] to1 = to.getChildren();
188: err.log(" getting children of from");
189: DataObject[] from1 = from.getChildren();
190:
191: class Queri extends Thread implements FileChangeListener,
192: DataLoader.RecognizedFiles, PropertyChangeListener {
193: public boolean stop;
194: private List deleted = Collections
195: .synchronizedList(new ArrayList());
196: public Exception problem;
197:
198: public Queri() {
199: super ("Query background thread");
200: setPriority(MAX_PRIORITY);
201: }
202:
203: public void fileFolderCreated(FileEvent fe) {
204: }
205:
206: public void fileDataCreated(FileEvent fe) {
207: }
208:
209: public void fileChanged(FileEvent fe) {
210: }
211:
212: public void fileDeleted(FileEvent fe) {
213: deleted.add(fe.getFile());
214: }
215:
216: public void fileRenamed(FileRenameEvent fe) {
217: }
218:
219: public void fileAttributeChanged(FileAttributeEvent fe) {
220: }
221:
222: public void run() {
223: while (!stop) {
224: FileObject[] arr = (FileObject[]) deleted
225: .toArray(new FileObject[0]);
226: DataLoader loader = SimpleLoader
227: .getLoader(SimpleLoader.class);
228: err.log("Next round");
229: for (int i = 0; i < arr.length; i++) {
230: try {
231: err.log("Checking " + arr[i]);
232: DataObject x = loader.findDataObject(
233: arr[i], this );
234: err.log(" has dobj: " + x);
235: } catch (IOException ex) {
236: if (problem == null) {
237: problem = ex;
238: }
239: }
240: }
241: }
242: }
243:
244: public void markRecognized(FileObject fo) {
245: }
246:
247: public void propertyChange(PropertyChangeEvent evt) {
248: if ("afterMove".equals(evt.getPropertyName())) {
249: Thread.yield();
250: }
251: }
252: }
253:
254: Queri que = new Queri();
255:
256: to.getPrimaryFile().addFileChangeListener(que);
257: from.getPrimaryFile().addFileChangeListener(que);
258:
259: que.start();
260: try {
261: for (int i = 0; i < 10; i++) {
262: err.log(i + " moving the object");
263: one.move(to);
264: err.log(i + " moving back");
265: one.move(from);
266: err.log(i + " end of cycle");
267: }
268: } finally {
269: que.stop = true;
270: }
271:
272: que.join();
273: if (que.problem != null) {
274: throw que.problem;
275: }
276:
277: assertEquals("Fourty deleted files:" + que.deleted, 40,
278: que.deleted.size());
279: }
280:
281: public void testAdditionsToCookieSetAreVisibleInLookup()
282: throws Exception {
283: assertTrue(this .one instanceof SimpleObject);
284: SimpleObject s = (SimpleObject) this .one;
285:
286: class Open implements OpenCookie {
287: public void open() {
288: }
289: }
290: Open openCookie = new Open();
291:
292: s.getCookieSet().add(openCookie);
293:
294: assertSame("Cookie is in the lookup", openCookie, one
295: .getLookup().lookup(OpenCookie.class));
296: }
297:
298: public static final class Pool extends DataLoaderPool {
299: protected Enumeration loaders() {
300: return Enumerations.singleton(SimpleLoader
301: .getLoader(SimpleLoader.class));
302: }
303: }
304:
305: public static final class SimpleLoader extends MultiFileLoader {
306: public SimpleLoader() {
307: super (SimpleObject.class);
308: }
309:
310: protected String displayName() {
311: return "SimpleLoader";
312: }
313:
314: protected FileObject findPrimaryFile(FileObject fo) {
315: if (!fo.isFolder()) {
316: // emulate the behaviour of form data object
317:
318: /* emulate!? this one is written too well ;-)
319: FileObject primary = FileUtil.findBrother(fo, "prima");
320: FileObject secondary = FileUtil.findBrother(fo, "seconda");
321:
322: if (primary == null || secondary == null) {
323: return null;
324: }
325:
326: if (primary != fo && secondary != fo) {
327: return null;
328: }
329: */
330:
331: // here is the common code for the worse behaviour
332: if (fo.hasExt("prima")) {
333: return FileUtil.findBrother(fo, "seconda") != null ? fo
334: : null;
335: }
336:
337: if (fo.hasExt("seconda")) {
338: return FileUtil.findBrother(fo, "prima");
339: }
340: }
341: return null;
342: }
343:
344: protected MultiDataObject createMultiObject(
345: FileObject primaryFile)
346: throws DataObjectExistsException, IOException {
347: return new SimpleObject(this , primaryFile);
348: }
349:
350: protected MultiDataObject.Entry createPrimaryEntry(
351: MultiDataObject obj, FileObject primaryFile) {
352: return new FileEntry(obj, primaryFile);
353: }
354:
355: protected MultiDataObject.Entry createSecondaryEntry(
356: MultiDataObject obj, FileObject secondaryFile) {
357: return new FileEntry(obj, secondaryFile);
358: }
359:
360: private void afterMove(FileObject f, FileObject retValue) {
361: firePropertyChange("afterMove", null, null);
362: }
363: }
364:
365: private static final class FE extends FileEntry {
366: public FE(MultiDataObject mo, FileObject fo) {
367: super (mo, fo);
368: }
369:
370: public FileObject move(FileObject f, String suffix)
371: throws IOException {
372: FileObject retValue;
373: retValue = super .move(f, suffix);
374:
375: SimpleLoader l = (SimpleLoader) getDataObject().getLoader();
376: l.afterMove(f, retValue);
377:
378: return retValue;
379: }
380:
381: }
382:
383: public static final class SimpleObject extends MultiDataObject {
384: public SimpleObject(SimpleLoader l, FileObject fo)
385: throws DataObjectExistsException {
386: super(fo, l);
387: }
388: }
389:
390: }
|