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.netbeans.modules.visualweb.complib;
043:
044: import java.io.File;
045: import java.io.IOException;
046: import java.net.URL;
047: import java.util.ArrayList;
048: import java.util.Arrays;
049: import java.util.Collections;
050: import java.util.List;
051: import java.util.ListResourceBundle;
052: import java.util.Locale;
053: import java.util.MissingResourceException;
054: import java.util.ResourceBundle;
055: import java.util.jar.Attributes;
056: import java.util.jar.Manifest;
057:
058: import org.netbeans.modules.visualweb.complib.Complib.InitialPaletteFolder;
059: import org.netbeans.modules.visualweb.complib.Complib.InitialPaletteItem;
060: import org.netbeans.modules.visualweb.complib.api.ComplibException;
061: import org.w3c.dom.Attr;
062: import org.w3c.dom.Document;
063: import org.w3c.dom.Element;
064: import org.w3c.dom.Node;
065: import org.w3c.dom.NodeList;
066: import org.w3c.dom.Text;
067:
068: /**
069: * Represents configuration information for a component library.
070: *
071: * @author Edwin Goei
072: */
073: class ComplibManifest {
074:
075: static final String MISSING = "Missing attribute: "; // NOI18N
076:
077: static final String PREFIX = "X-Rave-"; // NOI18N
078:
079: private static final String MISSING_RESOURCE = "Missing resource: "; // NOI18N
080:
081: private static final String API_COMPAT_VERSION = PREFIX
082: + "API-Compatibility-Version"; // NOI18N
083:
084: private static final Version VERSION_1_0_0 = new Version(1, 0, 0);
085:
086: private static final Version VERSION_2_0_0 = new Version(2, 0, 0);
087:
088: private static final String CONFIGURATION = PREFIX
089: + "Complib-Configuration"; // NOI18N
090:
091: private static final String ELM_ROOT = "complibConfiguration"; // NOI18N
092:
093: private static final String ELM_DESIGN_TIME_PATH = "designTimePath";
094:
095: private static final String ATT_RESOURCE_BUNDLE = "resourceBundleBaseName"; // NOI18N
096:
097: /** Used to look in META-INF/ as a fall back */
098: private static final String RESOURCE_BUNDLE_PREFIX = "META-INF.";
099:
100: /** XPath constants begin with XP_ */
101:
102: private static final String XP_PREFIX = "/" + ELM_ROOT + "/"; // NOI18N
103:
104: private static final String XP_CONFIG_VERSION = XP_PREFIX
105: + "@version"; // NOI18N
106:
107: private static final String XP_IDENTIFIER_URI = XP_PREFIX
108: + "identifier/uri/text()"; // NOI18N
109:
110: private static final String XP_IDENTIFIER_VERSION = XP_PREFIX
111: + "identifier/version/text()"; // NOI18N
112:
113: private static final String XP_TITLE_KEY = XP_PREFIX
114: + "titleKey/text()"; // NOI18N
115:
116: private static final String XP_RUNTIME_PATH = XP_PREFIX
117: + "runtimePath"; // NOI18N
118:
119: private static final String XP_DESIGN_TIME_PATH = XP_PREFIX
120: + ELM_DESIGN_TIME_PATH; // NOI18N
121:
122: private static final String XP_JAVADOC_PATH = XP_PREFIX
123: + "javadocPath"; // NOI18N
124:
125: private static final String XP_SOURCE_PATH = XP_PREFIX
126: + "sourcePath"; // NOI18N
127:
128: private static final String XP_WEB_RESOURCE_PATH = XP_PREFIX
129: + "webResourcePath"; // NOI18N
130:
131: private static final String XP_HELP_PATH = XP_PREFIX + "helpPath"; // NOI18N
132:
133: private static final String XP_HELP_PREFIX = XP_HELP_PATH
134: + "/@helpPrefix"; // NOI18N
135:
136: /** @since NetBeans Visual Web 6 */
137: private static final String XP_HELP_SET_FILE = XP_HELP_PATH
138: + "/@helpSetFile"; // NOI18N
139:
140: private static final String XP_INITIAL_PALETTE_FOLDER = XP_PREFIX
141: + "initialPalette/folder"; // NOI18N
142:
143: private static final String XP_PATH_ELEMENT = "pathElement"; // NOI18N
144:
145: private static final String XP_EE_SPEC_VERSION = XP_PREFIX
146: + "eeSpecification/@version"; // NOI18N
147:
148: private static final String XP_SUN_FACES_CONFIG = XP_PREFIX
149: + "sunFacesConfig/text()"; // NOI18N
150:
151: private static final String ATT_CLASS_NAME = "className"; // NOI18N
152:
153: private static final String ELM_ITEM = "item"; // NOI18N
154:
155: private static final String ATT_KEY = "key"; // NOI18N
156:
157: private static final String REQUIRES = "Complib configuration requires: "; // NOI18N
158:
159: private static final String BAD_VALUE = "Complib configuration has invalid value for: "; // NOI18N
160:
161: private static String complibConfigAttr;
162:
163: /** complibConfiguration XML document */
164: private Document doc;
165:
166: /**
167: * Resource bundle used to localize metadata for this complib package. Use
168: * this.getResource(String) to get localized messages.
169: */
170: private ResourceBundle rb;
171:
172: private static final EmptyResourceBundle emptyResourceBundle = new EmptyResourceBundle();
173:
174: private ArrayList<InitialPaletteFolder> topFolders = new ArrayList<InitialPaletteFolder>();
175:
176: /** Identifier is unique among all installed libraries */
177: protected Complib.Identifier identifier;
178:
179: /** Localized Title for this complib */
180: protected String title;
181:
182: /** Runtime path, each String is a relative complib resource path */
183: protected List<String> runtimePath;
184:
185: /** Design-time path, each String is a relative complib resource path */
186: protected List<String> declaredDesignTimePath;
187:
188: /** True iff runtime path should be prepended to design-time path */
189: protected boolean prependRuntimePath;
190:
191: /** Javadoc path, each String is a relative complib resource path */
192: protected List<String> javadocPath;
193:
194: /** Java source path, each String is a relative complib resource path */
195: protected List<String> sourcePath;
196:
197: /** Web resource path, each String is a relative complib resource path */
198: private List<String> webResourcePath;
199:
200: /** Help path, each String is a relative complib resource path */
201: private List<String> helpPath;
202:
203: /** Help prefix that is associated with the help path */
204: private String helpPrefix;
205:
206: /**
207: * "/" separated path to HelpSet file relative to helpPath. eg. "help/my-help.hs"
208: */
209: private String helpSetFile;
210:
211: /**
212: * Relative complib resource path to a sun-faces-config.xml type code generator input file
213: */
214: private String sunFacesConfig;
215:
216: public enum EeSpecVersion {
217: J2EE_1_4, JAVA_EE_5
218: };
219:
220: /** Java EE spec version that this complib depends upon */
221: private EeSpecVersion eeSpecVersion;
222:
223: private static XmlUtil configXmlUtil;
224:
225: private static final List<String> EMPTY_LIST = Collections
226: .emptyList();
227:
228: /**
229: * Represents legacy component library configuration info that was in Reef, AKA Rave version
230: * 1.x.
231: *
232: * @author Edwin Goei
233: */
234: static class LegacyManifest extends ComplibManifest {
235: /** The ordered pair (Library-URI, Library-Version) must be unique */
236: private static final String LIBRARY_URI = PREFIX
237: + "Library-URI"; // NOI18N
238:
239: /** The ordered pair (Library-URI, Library-Version) must be unique */
240: private static final String LIBRARY_VERSION = PREFIX
241: + "Library-Version"; // NOI18N
242:
243: /** Library-Title used as a user-friendly name which may not be unique */
244: private static final String LIBRARY_TITLE = PREFIX
245: + "Library-Title"; // NOI18N
246:
247: private static final String RUNTIME_PATH = PREFIX
248: + "Runtime-Path"; // NOI18N
249:
250: private static final String DESIGN_TIME_PATH = PREFIX
251: + "Design-Time-Path"; // NOI18N
252:
253: private static final String JAVADOC_PATH = PREFIX
254: + "Javadoc-Path"; // NOI18N
255:
256: private static final String SOURCE_PATH = PREFIX
257: + "Source-Path"; // NOI18N
258:
259: /**
260: * Parse legacy version 1.0 complib configuration
261: *
262: * @param attrs
263: * complib manifest attributes
264: * @throws ComplibException
265: */
266: public LegacyManifest(Attributes attrs) throws ComplibException {
267:
268: // Library URI is required
269: String valLibraryUri = attrs.getValue(LIBRARY_URI);
270: if (valLibraryUri == null) {
271: throw new ManifestAttributeException(MISSING
272: + LIBRARY_URI);
273: }
274:
275: // Library Version is required
276: String valLibraryVersion = attrs.getValue(LIBRARY_VERSION);
277: if (valLibraryVersion == null) {
278: throw new ManifestAttributeException(MISSING
279: + LIBRARY_VERSION);
280: }
281: this .identifier = new Complib.Identifier(valLibraryUri,
282: valLibraryVersion);
283:
284: String val;
285:
286: // Library Title is required
287: val = attrs.getValue(LIBRARY_TITLE);
288: if (val == null) {
289: throw new ManifestAttributeException(MISSING
290: + LIBRARY_TITLE);
291: }
292: this .title = val;
293:
294: // At least one Runtime jar is required
295: val = attrs.getValue(RUNTIME_PATH);
296: if (val == null || "".equals(val.trim())) {
297: throw new ManifestAttributeException(MISSING
298: + RUNTIME_PATH);
299: }
300: this .runtimePath = splitPath(val);
301:
302: // At least one Design-time jar is required
303: val = attrs.getValue(DESIGN_TIME_PATH);
304: if (val == null || "".equals(val.trim())) {
305: throw new ManifestAttributeException(MISSING
306: + DESIGN_TIME_PATH);
307: }
308: this .declaredDesignTimePath = splitPath(val);
309:
310: ArrayList<String> al = new ArrayList<String>(runtimePath);
311: al.addAll(splitPath(val));
312:
313: // Javadoc will be added to library reference, if any
314: this .javadocPath = splitPath(attrs.getValue(JAVADOC_PATH));
315:
316: // Source will be added to library reference, if any
317: this .sourcePath = splitPath(attrs.getValue(SOURCE_PATH));
318: }
319:
320: /**
321: * Split a path string using whitespace as a delimiter
322: *
323: * @param path
324: * whitespace separated path
325: * @return List of String-s, possibly empty, never null
326: */
327: private List<String> splitPath(String path) {
328: if (path == null) {
329: return new ArrayList<String>(0);
330: }
331: String[] parts = path.split("\\s"); // NOI18N
332: return Arrays.asList(parts);
333: }
334: }
335:
336: /**
337: * When no resource bundle is used, use a fake empty resource bundle so we don't have to special
338: * case for null later
339: */
340: private static class EmptyResourceBundle extends ListResourceBundle {
341:
342: private static final Object[][] contents = new Object[0][];
343:
344: protected Object[][] getContents() {
345: return contents;
346: }
347:
348: }
349:
350: /**
351: * Parse the Jar Manifest and return a CompLibManifest. This can occur before a package is
352: * expanded. This needs to be fast since a UI may depend on accessing some metadata about this
353: * library. Only some info such as the library Title is accessible before a package is expanded.
354: *
355: * @param manifest
356: * root jar Manifest which may refer to external resources
357: * @param resourceClassLoader
358: * ClassLoader used to load resources from
359: * @return
360: * @throws ComplibException
361: * @throws IOException
362: */
363: static ComplibManifest getInstance(Manifest manifest,
364: ClassLoader resourceClassLoader) throws ComplibException,
365: IOException {
366: // API Version attribute is required
367: Attributes attrs = manifest.getMainAttributes();
368:
369: String apiVersionString = attrs.getValue(API_COMPAT_VERSION);
370: if (apiVersionString == null) {
371: throw new ManifestAttributeException(MISSING
372: + API_COMPAT_VERSION);
373: }
374: Version apiVersion = new Version(apiVersionString);
375:
376: ComplibManifest compLibConfig;
377: if (VERSION_2_0_0.equals(apiVersion)) {
378: complibConfigAttr = attrs.getValue(CONFIGURATION);
379: if (complibConfigAttr == null) {
380: throw new ManifestAttributeException(MISSING
381: + CONFIGURATION);
382: }
383: URL complibConfUrl = resourceClassLoader
384: .getResource(complibConfigAttr);
385: if (complibConfUrl == null) {
386: throw new ComplibException(MISSING_RESOURCE
387: + complibConfigAttr);
388: }
389:
390: configXmlUtil = new XmlUtil();
391: Document configDoc = configXmlUtil.read(complibConfUrl);
392: compLibConfig = new ComplibManifest(configDoc,
393: resourceClassLoader);
394: } else if (VERSION_1_0_0.equals(apiVersion)) {
395: compLibConfig = new ComplibManifest.LegacyManifest(attrs);
396: } else {
397: throw new ManifestAttributeException(API_COMPAT_VERSION
398: + " must be " + VERSION_2_0_0 + " or "
399: + VERSION_1_0_0); // NOI18N
400: }
401:
402: return compLibConfig;
403: }
404:
405: static ComplibManifest getInstance(URL configUrl,
406: ClassLoader resourceClassLoader) throws ComplibException,
407: XmlException {
408: // TODO what about closing the doc??
409: Document configDoc = new XmlUtil().read(configUrl);
410: return new ComplibManifest(configDoc, resourceClassLoader);
411: }
412:
413: private ComplibManifest() {
414: // No-op. This default constructor is to allow subclassing.
415: }
416:
417: /**
418: * @param doc
419: * DOM that represents complib configuration metadata
420: * @param resourceClassLoader
421: * ClassLoader to load localized resources used for example for folder names
422: * @throws XmlException
423: * @throws ComplibException
424: */
425: private ComplibManifest(Document doc,
426: ClassLoader resourceClassLoader) throws XmlException,
427: ComplibException {
428: this .doc = doc;
429:
430: Element root = doc.getDocumentElement();
431: if (!ELM_ROOT.equals(root.getNodeName())) {
432: throw new ComplibException(
433: "Complib configuration root element must be '" // NOI18N
434: + ELM_ROOT + "'"); // NOI18N
435: }
436:
437: // Schema version of complib config file
438: Attr versionAttr = (Attr) XmlUtil.selectSingleNode(doc,
439: XP_CONFIG_VERSION);
440: String versionString = versionAttr.getValue();
441: int version;
442: if ("1.0".equals(versionString)) {
443: version = 1;
444: } else if ("1.1".equals(versionString)) {
445: // VWP 5.5, Shortfin
446: version = 11;
447: } else if ("1.2".equals(versionString)) {
448: // NetBeans 6 Visual Web, Longfin
449: version = 12;
450: } else {
451: throw new ComplibException(
452: "Complib configuration root element @version must be '1.0' or '1.1' or '1.2'"); // NOI18N
453: }
454:
455: initResourceBundle(root, resourceClassLoader);
456:
457: // Library URI is required
458: String libraryUri = getRequiredTextNode(XP_IDENTIFIER_URI);
459: // Library Version is required
460: String libraryVersion = getRequiredTextNode(XP_IDENTIFIER_VERSION);
461: this .identifier = new Complib.Identifier(libraryUri,
462: libraryVersion);
463:
464: // Library Title is required
465: String titleKey = getRequiredTextNode(XP_TITLE_KEY);
466: this .title = getResource(titleKey);
467:
468: // At least one Runtime jar is required
469: this .runtimePath = getRequiredConfigPath(XP_RUNTIME_PATH);
470:
471: // Design-time jars, typically at least one, but no longer required
472: this .declaredDesignTimePath = getConfigPath(XP_DESIGN_TIME_PATH);
473:
474: // Javadoc will be added to library reference, if any
475: this .javadocPath = getConfigPath(XP_JAVADOC_PATH);
476:
477: // Source will be added to library reference, if any
478: this .sourcePath = getConfigPath(XP_SOURCE_PATH);
479:
480: // Resources will be unpacked and merged with project web resources
481: this .webResourcePath = getConfigPath(XP_WEB_RESOURCE_PATH);
482:
483: // Help will be merged with IDE help
484: Attr attr = (Attr) XmlUtil
485: .selectSingleNode(doc, XP_HELP_PREFIX);
486: if (attr != null) {
487: this .helpPrefix = attr.getValue();
488: }
489: attr = (Attr) XmlUtil.selectSingleNode(doc, XP_HELP_SET_FILE);
490: if (attr != null) {
491: this .helpSetFile = attr.getValue();
492: }
493: this .helpPath = getConfigPath(XP_HELP_PATH);
494:
495: // Init the optional initial palette structure data
496: initPaletteData();
497:
498: // Default value is J2EE 1.4 for backward compatibility before VWP 5.5
499: eeSpecVersion = EeSpecVersion.J2EE_1_4;
500: // Value of null means not specified so use default
501: attr = (Attr) XmlUtil.selectSingleNode(doc, XP_EE_SPEC_VERSION);
502: String stringVal = attr == null ? null : attr.getValue();
503: // Complibs before VWP 5.5, will not contain this attribute
504: if (stringVal != null) {
505: if ("5".equals(stringVal)) {
506: eeSpecVersion = EeSpecVersion.JAVA_EE_5;
507: } else if (version > 11 && !"1.4".equals(stringVal)) {
508: // If VWP 5.5 and later, enforce fixed set of values
509: throw new ComplibException(BAD_VALUE
510: + XP_EE_SPEC_VERSION);
511: }
512: }
513: // Value of null means not specified
514: this .sunFacesConfig = getOptionalTextNode(XP_SUN_FACES_CONFIG,
515: null);
516: }
517:
518: /**
519: * @return
520: * @throws XmlException
521: * @throws ComplibException
522: * if required text node does not exist
523: */
524: private String getRequiredTextNode(String xpath)
525: throws XmlException, ComplibException {
526: Text text = (Text) XmlUtil.selectSingleNode(doc, xpath);
527: if (text == null) {
528: throw new ComplibException(REQUIRES + xpath);
529: }
530: return text.getNodeValue().trim();
531: }
532:
533: private String getOptionalTextNode(String xpath, String defaultVal)
534: throws XmlException {
535: Text text = (Text) XmlUtil.selectSingleNode(doc, xpath);
536: if (text == null) {
537: return defaultVal;
538: }
539: return text.getNodeValue().trim();
540: }
541:
542: /**
543: * Same as getConfigPath(String) but it requires at least one path element
544: *
545: * @param xpath
546: * @return
547: * @throws XmlException
548: * @throws ComplibException
549: * if no path elements are found
550: */
551: private List<String> getRequiredConfigPath(String xpath)
552: throws XmlException, ComplibException {
553: List<String> path = getConfigPath(xpath);
554: if (path.isEmpty()) {
555: throw new ComplibException(REQUIRES + xpath);
556: }
557: return path;
558: }
559:
560: /**
561: * Return a List of path elements within a path specified in the config
562: *
563: * @param xpath
564: * parent element containing path elements
565: * @return List of path elements which may be empty but never null
566: * @throws XmlException
567: */
568: private List<String> getConfigPath(String xpath)
569: throws XmlException {
570: ArrayList<String> path = new ArrayList<String>();
571: Element elm = (Element) XmlUtil.selectSingleNode(doc, xpath);
572: if (elm == null) {
573: // Empty path
574: return path;
575: }
576:
577: // Iterate through all XP_PATH_ELEMENT children
578: NodeList nl = XmlUtil.selectNodeList(elm, XP_PATH_ELEMENT);
579: for (int i = 0; i < nl.getLength(); i++) {
580: Element pathElmElm = (Element) nl.item(i);
581: Text pathElmText = (Text) XmlUtil.selectSingleNode(
582: pathElmElm, "text()"); // NOI18N
583: if (pathElmText != null) {
584: String val = pathElmText.getNodeValue();
585: if ("" != val.trim()) {
586: path.add(val);
587: }
588: }
589: }
590: return path;
591: }
592:
593: private boolean getBoolean(String xpath, boolean defaultValue)
594: throws XmlException {
595: Attr attr = (Attr) XmlUtil.selectSingleNode(doc, xpath);
596: if (attr == null) {
597: return defaultValue;
598: }
599: return "true".equalsIgnoreCase(attr.getValue().trim());
600: }
601:
602: private void initPaletteData() throws XmlException {
603: // Iterate through top level folders
604: NodeList nl = XmlUtil.selectNodeList(doc,
605: XP_INITIAL_PALETTE_FOLDER);
606: for (int i = 0; i < nl.getLength(); i++) {
607: Element elm = (Element) nl.item(i);
608: InitialPaletteFolder topFolder = createFolderRecurse(elm);
609: topFolders.add(topFolder);
610: }
611: }
612:
613: /**
614: * @param folderElement
615: * @return
616: * @throws XmlException
617: */
618: private InitialPaletteFolder createFolderRecurse(
619: Element folderElement) throws XmlException {
620: // Derive the localized name
621: String key = folderElement.getAttribute(ATT_KEY);
622: InitialPaletteFolder folder = new InitialPaletteFolder(
623: getResource(key));
624:
625: // Iterate through all Element child nodes
626: NodeList nl = XmlUtil.selectNodeList(folderElement, "*"); // NOI18N
627: for (int i = 0; i < nl.getLength(); i++) {
628: Element elm = (Element) nl.item(i);
629: String tagName = elm.getNodeName();
630: if (ELM_ITEM.equals(tagName)) {
631: InitialPaletteItem child = createItemRecurse(elm);
632: folder.appendChild(child);
633: } else {
634: // This also disallows a folder from containing another folder
635: IdeUtil.logWarning(new IllegalArgumentException(
636: "Skipping invalid element in initial palette: " // NOI18N
637: + tagName));
638: }
639: }
640: return folder;
641: }
642:
643: private InitialPaletteItem createItemRecurse(Element itemElement)
644: throws XmlException {
645: // Derive the localized name
646: String className = itemElement.getAttribute(ATT_CLASS_NAME);
647: InitialPaletteItem item = new InitialPaletteItem(className);
648:
649: // Iterate through all Element child nodes
650: NodeList nl = XmlUtil.selectNodeList(itemElement, "*");
651: for (int i = 0; i < nl.getLength(); i++) {
652: Element elm = (Element) nl.item(i);
653: String tagName = elm.getNodeName();
654: if (ELM_ITEM.equals(tagName)) {
655: InitialPaletteItem child = createItemRecurse(elm);
656: item.appendChild(child);
657: } else {
658: IdeUtil.logWarning(new IllegalArgumentException(
659: "Skipping invalid element in initial palette: " // NOI18N
660: + tagName));
661: }
662: }
663: return item;
664: }
665:
666: /**
667: * Init ResourceBundle baseName which is optional
668: *
669: * @param complibConfigurationElm
670: * @param resourceClassLoader
671: */
672: private void initResourceBundle(Element complibConfigurationElm,
673: ClassLoader resourceClassLoader) {
674: String rbBaseName = complibConfigurationElm
675: .getAttribute(ATT_RESOURCE_BUNDLE);
676: if (rbBaseName.length() != 0) {
677: // Attribute was specified or defaulted
678: try {
679: /*
680: * As a workaround for the NB ProxyClassLoader warning, look for the bundle under
681: * META-INF first and then go look starting at the top level as usual.
682: *
683: * @since NetBeans 6 Visual Web
684: */
685: if (rbBaseName.indexOf(".") == -1) {
686: try {
687: rb = ResourceBundle.getBundle(
688: RESOURCE_BUNDLE_PREFIX + rbBaseName,
689: Locale.getDefault(),
690: resourceClassLoader);
691: } catch (MissingResourceException mre) {
692: rb = ResourceBundle.getBundle(rbBaseName,
693: Locale.getDefault(),
694: resourceClassLoader);
695: }
696: } else {
697: rb = ResourceBundle.getBundle(rbBaseName, Locale
698: .getDefault(), resourceClassLoader);
699: }
700: } catch (RuntimeException e) {
701: // Fallback: warn user and default to using no resource bundle
702: IdeUtil.logWarning(e);
703: rb = emptyResourceBundle;
704: }
705: } else {
706: // Assume no localization was desired.
707: rb = emptyResourceBundle;
708: }
709: }
710:
711: /**
712: * Return a value from a resource bundle or the key itself if this is not possible.
713: *
714: * @param key
715: * @return value correspinding to key or key itself
716: */
717: private String getResource(String key) {
718: try {
719: String value = rb.getString(key);
720: return value;
721: } catch (RuntimeException e) {
722: if (rb != emptyResourceBundle) {
723: // Warn if we're using a user supplied resource bundle
724: IdeUtil.logWarning(e);
725: }
726: // Use the key itself as the value
727: return key;
728: }
729: }
730:
731: /**
732: * Returns a List<InitialPaletteFolder> representing the initial palette structure for this
733: * complib, if any. If the list is empty, then this complib does not have an initial palette
734: * specified.
735: *
736: * @return List<InitialPaletteFolder> which may be empty but never null.
737: */
738: List<InitialPaletteFolder> getInitialPalette() {
739: return topFolders;
740: }
741:
742: List<String> getDeclaredDesignTimePath() {
743: return declaredDesignTimePath;
744: }
745:
746: List<String> getHelpPath() {
747: return helpPath == null ? EMPTY_LIST : helpPath;
748: }
749:
750: String getHelpSetFile() {
751: return helpSetFile;
752: }
753:
754: /**
755: * Return the help prefix. Null means no prefix attribute found.
756: *
757: * @return
758: */
759: String getHelpPrefix() {
760: return helpPrefix;
761: }
762:
763: Complib.Identifier getIdentifier() {
764: return identifier;
765: }
766:
767: List<String> getJavadocPath() {
768: return javadocPath == null ? EMPTY_LIST : javadocPath;
769: }
770:
771: List<String> getRuntimePath() {
772: return runtimePath;
773: }
774:
775: List<String> getSourcePath() {
776: return sourcePath == null ? EMPTY_LIST : sourcePath;
777: }
778:
779: String getTitle() {
780: return title;
781: }
782:
783: List<String> getWebResourcePath() {
784: return webResourcePath == null ? EMPTY_LIST : webResourcePath;
785: }
786:
787: public EeSpecVersion getEeSpecVersion() {
788: return eeSpecVersion;
789: }
790:
791: /**
792: * @return null if not specified
793: */
794: String getSunFacesConfig() {
795: return sunFacesConfig;
796: }
797:
798: /**
799: * Append a single design-time jar element to the declared design-time path
800: *
801: * @param dtJar
802: * @throws XmlException
803: */
804: void addDeclaredDesignTimePath(File dtJar) throws XmlException {
805: // TODO this just picks the last component of path
806: String dtJarText = dtJar.getName();
807: declaredDesignTimePath.add(dtJarText);
808:
809: // Persist it in DOM
810: Element dtPathElm = (Element) XmlUtil.selectSingleNode(doc,
811: XP_DESIGN_TIME_PATH);
812: if (dtPathElm == null) {
813: // No DT path element so create it and insert it
814:
815: dtPathElm = doc.createElement(ELM_DESIGN_TIME_PATH);
816: Element rtPathElm = (Element) XmlUtil.selectSingleNode(doc,
817: XP_RUNTIME_PATH);
818: Element parentElm = (Element) rtPathElm.getParentNode();
819: Node insertNode = rtPathElm.getNextSibling();
820: parentElm.insertBefore(dtPathElm, insertNode);
821: }
822:
823: Text textNode = doc.createTextNode(dtJarText);
824: Element pathElementElm = doc.createElement(XP_PATH_ELEMENT);
825: pathElementElm.appendChild(textNode);
826: dtPathElm.appendChild(pathElementElm);
827:
828: }
829:
830: /**
831: * @param absoluteLibDir
832: * @throws XmlException
833: */
834: void saveTo(File absoluteLibDir) throws XmlException {
835: File destConfig = new File(absoluteLibDir, complibConfigAttr);
836: configXmlUtil.write(destConfig);
837: }
838: }
|