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.modules.project.libraries;
043:
044: import java.beans.PropertyChangeEvent;
045: import java.beans.PropertyChangeListener;
046: import java.beans.PropertyChangeSupport;
047: import java.io.IOException;
048: import java.io.OutputStreamWriter;
049: import java.io.PrintWriter;
050: import java.io.StringReader;
051: import java.net.URL;
052: import java.util.ArrayList;
053: import java.util.Arrays;
054: import java.util.Collections;
055: import java.util.HashMap;
056: import java.util.HashSet;
057: import java.util.List;
058: import java.util.Map;
059: import java.util.Set;
060: import java.util.StringTokenizer;
061: import org.netbeans.api.project.TestUtil;
062: import org.netbeans.junit.NbTestCase;
063: import org.netbeans.spi.project.libraries.LibraryImplementation;
064: import org.netbeans.spi.project.libraries.LibraryProvider;
065: import org.netbeans.spi.project.libraries.LibraryTypeProvider;
066: import org.openide.filesystems.FileLock;
067: import org.openide.filesystems.FileObject;
068: import org.openide.filesystems.FileSystem;
069: import org.openide.filesystems.Repository;
070: import org.openide.loaders.DataFolder;
071: import org.openide.loaders.InstanceDataObject;
072: import org.openide.util.Lookup;
073: import org.openide.xml.EntityCatalog;
074: import org.xml.sax.InputSource;
075: import org.xml.sax.SAXException;
076:
077: /**
078: *
079: * @author Tomas Zezula
080: */
081: public class LibrariesStorageTest extends NbTestCase {
082:
083: private FileObject storageFolder;
084: LibrariesStorage storage;
085:
086: public LibrariesStorageTest(String testName) {
087: super (testName);
088: }
089:
090: protected void setUp() throws Exception {
091: super .setUp();
092: TestUtil.setLookup(new Object[] { new TestEntityCatalog() });
093: this .registerLibraryTypeProvider();
094: this .storageFolder = TestUtil.makeScratchDir(this );
095: this .createLibraryDefinition(this .storageFolder, "Library1");
096: this .storage = new LibrariesStorage(this .storageFolder);
097: }
098:
099: public void testGetLibraries() throws Exception {
100: this .storage.getLibraries();
101: LibraryImplementation[] libs = this .storage.getLibraries();
102: assertEquals("Libraries count", 1, libs.length);
103: assertLibEquals(libs, new String[] { "Library1" });
104: createLibraryDefinition(this .storageFolder, "Library2");
105: libs = this .storage.getLibraries();
106: assertEquals("Libraries count", 2, libs.length);
107: assertLibEquals(libs, new String[] { "Library1", "Library2" });
108: TestListener l = new TestListener();
109: this .storage.addPropertyChangeListener(l);
110: TestLibraryTypeProvider tlp = (TestLibraryTypeProvider) LibraryTypeRegistry
111: .getDefault().getLibraryTypeProvider(
112: TestLibraryTypeProvider.TYPE);
113: tlp.reset();
114: createLibraryDefinition(this .storageFolder, "Library3");
115: libs = this .storage.getLibraries();
116: assertEquals("Libraries count", 3, libs.length);
117: assertLibEquals(libs, new String[] { "Library1", "Library2",
118: "Library3" });
119: assertEquals("Event count", 1, l.getEventNames().size());
120: assertEquals("Event names", LibraryProvider.PROP_LIBRARIES, l
121: .getEventNames().get(0));
122: assertTrue("Library created called", tlp.wasCreatedCalled());
123: }
124:
125: public void testAddLibrary() throws Exception {
126: this .storage.getLibraries();
127: LibraryImplementation[] libs = this .storage.getLibraries();
128: assertEquals("Libraries count", 1, libs.length);
129: assertLibEquals(libs, new String[] { "Library1" });
130: TestLibraryTypeProvider tlp = (TestLibraryTypeProvider) LibraryTypeRegistry
131: .getDefault().getLibraryTypeProvider(
132: TestLibraryTypeProvider.TYPE);
133: tlp.reset();
134: LibraryImplementation impl = new TestLibrary("Library2");
135: this .storage.addLibrary(impl);
136: libs = this .storage.getLibraries();
137: assertEquals("Libraries count", 2, libs.length);
138: assertLibEquals(libs, new String[] { "Library1", "Library2" });
139: assertTrue(tlp.wasCreatedCalled());
140: }
141:
142: public void testRemoveLibrary() throws Exception {
143: this .storage.getLibraries();
144: LibraryImplementation[] libs = this .storage.getLibraries();
145: assertEquals("Libraries count", 1, libs.length);
146: assertLibEquals(libs, new String[] { "Library1" });
147: TestLibraryTypeProvider tlp = (TestLibraryTypeProvider) LibraryTypeRegistry
148: .getDefault().getLibraryTypeProvider(
149: TestLibraryTypeProvider.TYPE);
150: tlp.reset();
151: this .storage.removeLibrary(libs[0]);
152: libs = this .storage.getLibraries();
153: assertEquals("Libraries count", 0, libs.length);
154: assertTrue("Library deleted called", tlp.wasDeletedCalled());
155: }
156:
157: public void testUpdateLibrary() throws Exception {
158: this .storage.getLibraries();
159: LibraryImplementation[] libs = this .storage.getLibraries();
160: assertEquals("Libraries count", 1, libs.length);
161: assertLibEquals(libs, new String[] { "Library1" });
162: TestLibraryTypeProvider tlp = (TestLibraryTypeProvider) LibraryTypeRegistry
163: .getDefault().getLibraryTypeProvider(
164: TestLibraryTypeProvider.TYPE);
165: tlp.reset();
166: LibraryImplementation newLib = new TestLibrary(
167: (TestLibrary) libs[0]);
168: newLib.setName("NewLibrary");
169: this .storage.updateLibrary(libs[0], newLib);
170: libs = this .storage.getLibraries();
171: assertEquals("Libraries count", 1, libs.length);
172: assertLibEquals(libs, new String[] { "NewLibrary" });
173: assertTrue("Library created called", tlp.wasCreatedCalled());
174: }
175:
176: private static void assertLibEquals(LibraryImplementation[] libs,
177: String[] names) {
178: assertEquals("Libraries Equals (size)", names.length,
179: libs.length);
180: Set<String> s = new HashSet<String>(Arrays.asList(names)); //Ordering is not important
181: for (LibraryImplementation lib : libs) {
182: String name = lib.getName();
183: assertTrue("Libraries Equals (unknown library " + name
184: + ")", s.remove(name));
185: }
186: }
187:
188: private static void registerLibraryTypeProvider() throws Exception {
189: StringTokenizer tk = new StringTokenizer(
190: "org-netbeans-api-project-libraries/LibraryTypeProviders",
191: "/");
192: FileObject root = Repository.getDefault()
193: .getDefaultFileSystem().getRoot();
194: while (tk.hasMoreElements()) {
195: String pathElement = tk.nextToken();
196: FileObject tmp = root.getFileObject(pathElement);
197: if (tmp == null) {
198: tmp = root.createFolder(pathElement);
199: }
200: root = tmp;
201: }
202: if (root.getChildren().length == 0) {
203: // FileObject inst = root.createData("TestLibraryTypeProvider","instance");
204: // inst.setAttribute("newvalue","")
205: InstanceDataObject.create(DataFolder.findFolder(root),
206: "TestLibraryTypeProvider",
207: TestLibraryTypeProvider.class);
208: }
209: }
210:
211: private static void createLibraryDefinition(
212: final FileObject storageFolder, final String libName)
213: throws IOException {
214: storageFolder.getFileSystem().runAtomicAction(
215: new FileSystem.AtomicAction() {
216: public void run() throws IOException {
217: FileObject defFile = storageFolder.createData(
218: libName, "xml");
219: FileLock lock = null;
220: PrintWriter out = null;
221: try {
222: lock = defFile.lock();
223: out = new PrintWriter(
224: new OutputStreamWriter(defFile
225: .getOutputStream(lock),
226: "UTF-8"));
227: out
228: .println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); //NOI18N
229: out
230: .println("<!DOCTYPE library PUBLIC \"-//NetBeans//DTD Library Declaration 1.0//EN\" \"http://www.netbeans.org/dtds/library-declaration-1_0.dtd\">");
231: out.println("<library version=\"1.0\">");
232: out.println("\t<name>" + libName
233: + "</name>");
234: out.println("\t<type>"
235: + TestLibraryTypeProvider.TYPE
236: + "</type>");
237: for (int i = 0; i < TestLibraryTypeProvider.supportedTypes.length; i++) {
238: out.println("\t<volume>");
239: out
240: .println("\t\t<type>"
241: + TestLibraryTypeProvider.supportedTypes[i]
242: + "</type>");
243: out.println("\t</volume>");
244: }
245: out.println("</library>");
246: } finally {
247: if (out != null)
248: out.close();
249: if (lock != null)
250: lock.releaseLock();
251: }
252: }
253: });
254: }
255:
256: private static class TestListener implements PropertyChangeListener {
257:
258: private List<String> eventNames = new ArrayList<String>();
259:
260: public List<String> getEventNames() {
261: return this .eventNames;
262: }
263:
264: public void propertyChange(
265: PropertyChangeEvent propertyChangeEvent) {
266: this .eventNames.add(propertyChangeEvent.getPropertyName());
267: }
268:
269: public void reset() {
270: this .eventNames.clear();
271: }
272:
273: }
274:
275: private static class TestEntityCatalog extends EntityCatalog {
276:
277: private static final String DTD = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
278: + "<!ELEMENT library (name, type, description?, localizing-bundle?, volume*) >\n"
279: + "<!ATTLIST library version CDATA #FIXED \"1.0\" >\n"
280: + "<!ELEMENT name (#PCDATA) >\n"
281: + "<!ELEMENT description (#PCDATA) >\n"
282: + "<!ELEMENT localizing-bundle (#PCDATA)>\n"
283: + "<!ELEMENT volume (type, resource*) >\n"
284: + "<!ELEMENT type (#PCDATA) >\n"
285: + "<!ELEMENT resource (#PCDATA) >\n";
286:
287: public InputSource resolveEntity(String str, String str1)
288: throws SAXException, IOException {
289: if ("-//NetBeans//DTD Library Declaration 1.0//EN"
290: .equals(str)) {
291: InputSource in = new InputSource(new StringReader(DTD));
292: return in;
293: } else {
294: return null;
295: }
296: }
297: }
298:
299: public static class TestLibraryTypeProvider implements
300: LibraryTypeProvider, java.io.Serializable {
301:
302: static final String[] supportedTypes = new String[] { "bin",
303: "src" };
304:
305: static final String TYPE = "Test";
306:
307: private boolean createdCalled;
308:
309: private boolean deletedCalled;
310:
311: public java.beans.Customizer getCustomizer(String volumeType) {
312: return null;
313: }
314:
315: public void libraryDeleted(LibraryImplementation libraryImpl) {
316: this .deletedCalled = true;
317: }
318:
319: public void libraryCreated(LibraryImplementation libraryImpl) {
320: this .createdCalled = true;
321: }
322:
323: public void reset() {
324: this .createdCalled = false;
325: this .deletedCalled = false;
326: }
327:
328: public boolean wasCreatedCalled() {
329: return this .createdCalled;
330: }
331:
332: public boolean wasDeletedCalled() {
333: return this .deletedCalled;
334: }
335:
336: public String[] getSupportedVolumeTypes() {
337: return supportedTypes;
338: }
339:
340: public Lookup getLookup() {
341: return Lookup.EMPTY;
342: }
343:
344: public String getLibraryType() {
345: return TYPE;
346: }
347:
348: public String getDisplayName() {
349: return "Test Library Type";
350: }
351:
352: public LibraryImplementation createLibrary() {
353: return new TestLibrary();
354: }
355:
356: }
357:
358: private static class TestLibrary implements LibraryImplementation {
359:
360: private String name;
361: private String locBundle;
362: private String description;
363: private Map<String, List<URL>> contents;
364: private PropertyChangeSupport support;
365:
366: public TestLibrary() {
367: this .support = new PropertyChangeSupport(this );
368: this .contents = new HashMap<String, List<URL>>(2);
369: }
370:
371: public TestLibrary(String name) {
372: this ();
373: this .name = name;
374: }
375:
376: public TestLibrary(TestLibrary lib) {
377: this ();
378: this .name = lib.name;
379: this .locBundle = lib.locBundle;
380: this .description = lib.description;
381: this .contents = lib.contents;
382: }
383:
384: public String getType() {
385: return TestLibraryTypeProvider.TYPE;
386: }
387:
388: public String getName() {
389: return this .name;
390: }
391:
392: public void setName(String name) {
393: this .name = name;
394: this .support.firePropertyChange(PROP_NAME, null, null);
395: }
396:
397: public String getLocalizingBundle() {
398: return this .locBundle;
399: }
400:
401: public void setLocalizingBundle(String resourceName) {
402: this .locBundle = resourceName;
403: this .support.firePropertyChange("localizingBundle", null,
404: null);
405: }
406:
407: public String getDescription() {
408: return this .description;
409: }
410:
411: public void setDescription(String text) {
412: this .description = text;
413: this .support.firePropertyChange(PROP_DESCRIPTION, null,
414: null);
415: }
416:
417: public List<URL> getContent(String volumeType)
418: throws IllegalArgumentException {
419: for (String t : TestLibraryTypeProvider.supportedTypes) {
420: if (t.equals(volumeType)) {
421: List<URL> l = this .contents.get(volumeType);
422: if (l == null) {
423: l = Collections.emptyList();
424: }
425: return l;
426: }
427: }
428: throw new IllegalArgumentException();
429: }
430:
431: public void setContent(String volumeType, List<URL> path)
432: throws IllegalArgumentException {
433: for (String t : TestLibraryTypeProvider.supportedTypes) {
434: if (t.equals(volumeType)) {
435: List<URL> l = this .contents.put(volumeType, path);
436: this .support.firePropertyChange(PROP_CONTENT, null,
437: null);
438: return;
439: }
440: }
441: throw new IllegalArgumentException();
442: }
443:
444: public void addPropertyChangeListener(
445: java.beans.PropertyChangeListener l) {
446: this .support.addPropertyChangeListener(l);
447: }
448:
449: public void removePropertyChangeListener(
450: java.beans.PropertyChangeListener l) {
451: this.support.removePropertyChangeListener(l);
452: }
453: }
454:
455: }
|