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: * If you wish your version of this file to be governed by only the CDDL
025: * or only the GPL Version 2, indicate your decision by adding
026: * "[Contributor] elects to include this software in this distribution
027: * under the [CDDL or GPL Version 2] license." If you do not indicate a
028: * single choice of license, a recipient has the option to distribute
029: * your version of this file under either the CDDL, the GPL Version 2 or
030: * to extend the choice of license to its licensees as provided above.
031: * However, if you add GPL Version 2 code and therefore, elected the GPL
032: * Version 2 license, then the option applies only if the new code is
033: * made subject to such option by the copyright holder.
034: *
035: * Contributor(s):
036: *
037: * Portions Copyrighted 2008 Sun Microsystems, Inc.
038: */
039:
040: package org.netbeans.modules.java.api.common.classpath.j2ee;
041:
042: import java.io.File;
043: import java.net.URI;
044: import java.util.ArrayList;
045: import java.util.Arrays;
046: import java.util.Collections;
047: import java.util.Iterator;
048: import java.util.List;
049: import org.netbeans.api.project.ant.AntArtifact;
050: import org.netbeans.api.project.libraries.Library;
051: import org.netbeans.modules.java.api.common.util.CommonProjectUtils;
052: import org.netbeans.modules.java.api.common.classpath.ClassPathItem;
053: import org.netbeans.spi.project.support.ant.AntProjectHelper;
054: import org.netbeans.spi.project.support.ant.PropertyEvaluator;
055: import org.netbeans.spi.project.support.ant.ReferenceHelper;
056: import org.w3c.dom.Document;
057: import org.w3c.dom.Element;
058: import org.w3c.dom.Node;
059: import org.w3c.dom.NodeList;
060: import org.w3c.dom.Text;
061:
062: // will be moved to j2ee.common
063: /**
064: *
065: * @author Tomas Mysik
066: * @since 1.21
067: */
068: public final class J2EEClassPathSupport extends
069: BaseClassPathSupport<J2EEClassPathSupport.Item> {
070:
071: private final String[] elementsOrder;
072:
073: // XXX javadoc
074: public static J2EEClassPathSupport create(
075: PropertyEvaluator evaluator,
076: ReferenceHelper referenceHelper,
077: AntProjectHelper antProjectHelper, String[] wellKnownPaths,
078: String libraryPrefix, String librarySuffix,
079: String antArtifactPrefix,
080: String projectConfigurationNameSpace, String[] elementsOrder) {
081: return new J2EEClassPathSupport(evaluator, referenceHelper,
082: antProjectHelper, wellKnownPaths, libraryPrefix,
083: librarySuffix, antArtifactPrefix,
084: projectConfigurationNameSpace, elementsOrder);
085: }
086:
087: private J2EEClassPathSupport(PropertyEvaluator evaluator,
088: ReferenceHelper referenceHelper,
089: AntProjectHelper antProjectHelper, String[] wellKnownPaths,
090: String libraryPrefix, String librarySuffix,
091: String antArtifactPrefix,
092: String projectConfigurationNameSpace, String[] elementsOrder) {
093: super (evaluator, referenceHelper, antProjectHelper,
094: wellKnownPaths, libraryPrefix, librarySuffix,
095: antArtifactPrefix, projectConfigurationNameSpace);
096:
097: this .elementsOrder = elementsOrder;
098: }
099:
100: @Override
101: public List<Item> itemsList(String propertyValue,
102: String libraryElementName) {
103: List<org.netbeans.modules.java.api.common.classpath.ClassPathSupport.Item> items = delegate
104: .itemsList(propertyValue);
105:
106: // get the list of items which are included in deployment
107: List<String> includedItems = null;
108: if (libraryElementName != null) {
109: includedItems = getIncludedLibraries(antProjectHelper,
110: libraryElementName);
111: } else {
112: includedItems = Collections.<String> emptyList();
113: }
114:
115: List<Item> result = new ArrayList<Item>(items.size());
116: for (org.netbeans.modules.java.api.common.classpath.ClassPathSupport.Item item : items) {
117: result.add(createItem(item, includedItems));
118: }
119: return result;
120: }
121:
122: @Override
123: public String[] encodeToStrings(List<Item> items,
124: String libraryElementName) {
125: List<String> includedLibraries = new ArrayList<String>();
126:
127: List<String> result = new ArrayList<String>();
128: for (Item item : items) {
129: String reference = delegate.getReference(item.delegate);
130: if (reference != null) {
131: result.add(reference);
132: item.setReference(reference);
133:
134: // add the item to the list of items included in deployment
135: if (libraryElementName != null
136: && item.isIncludedInDeployment()) {
137: includedLibraries.add(CommonProjectUtils
138: .getAntPropertyName(reference));
139: }
140: }
141: }
142:
143: if (libraryElementName != null) {
144: List<Item> cp = new ArrayList<Item>(items);
145: putIncludedLibraries(includedLibraries, cp,
146: antProjectHelper, libraryElementName);
147: }
148:
149: // XXX create util method in Strings (core j2ee utilities)
150: String[] strings = new String[result.size()];
151: for (int i = 0; i < result.size(); i++) {
152: if (i < result.size() - 1) {
153: strings[i] = result.get(i) + ":"; //NOI18N
154: } else {
155: strings[i] = result.get(i);
156: }
157: }
158: return strings;
159: }
160:
161: private Item createItem(
162: final org.netbeans.modules.java.api.common.classpath.ClassPathSupport.Item delegate,
163: final List<String> includedItems) {
164: Item item = null;
165: switch (delegate.getType()) {
166: case CLASSPATH:
167: item = new Item(delegate, delegate.getReference(), false,
168: null);
169: break;
170: case LIBRARY:
171: case ARTIFACT:
172: case JAR:
173: String property = delegate.getReference();
174: item = new Item(delegate, property, includedItems
175: .contains(property), null);
176: break;
177: default:
178: assert false : "Unknown classpath item type for "
179: + delegate;
180: break;
181: }
182: return item;
183: }
184:
185: /**
186: * Returns a list with the classpath items which are to be included
187: * in deployment.
188: */
189: private List<String> getIncludedLibraries(
190: AntProjectHelper antProjectHelper, String libraryElementName) {
191: assert antProjectHelper != null;
192: assert libraryElementName != null;
193:
194: Element data = antProjectHelper
195: .getPrimaryConfigurationData(true);
196: NodeList libs = data.getElementsByTagNameNS(
197: projectConfigurationNameSpace, libraryElementName);
198: List<String> libraries = new ArrayList<String>(libs.getLength());
199: for (int i = 0; i < libs.getLength(); i++) {
200: Element item = (Element) libs.item(i);
201: libraries.add(findText(item));
202: }
203: return libraries;
204: }
205:
206: /**
207: * Updates the project helper with the list of classpath items which are to be
208: * included in deployment.
209: */
210: private void putIncludedLibraries(List<String> libraries,
211: List<Item> classpath, AntProjectHelper antProjectHelper,
212: String libraryElementName) {
213: assert libraries != null;
214: assert antProjectHelper != null;
215: assert libraryElementName != null;
216:
217: Element data = antProjectHelper
218: .getPrimaryConfigurationData(true);
219: NodeList libs = data.getElementsByTagNameNS(
220: projectConfigurationNameSpace, libraryElementName);
221: while (libs.getLength() > 0) {
222: Node n = libs.item(0);
223: n.getParentNode().removeChild(n);
224: }
225:
226: Document doc = data.getOwnerDocument();
227: for (String libraryName : libraries) {
228: // find a correcponding classpath item for the library
229: for (Item item : classpath) {
230: String libraryPropName = "${" + libraryName + "}"; // NOI18N
231: if (libraryPropName.equals(item.getReference())) {
232: Element element = createLibraryElement(doc,
233: libraryName, item, libraryElementName);
234: if (elementsOrder != null) {
235: appendChildElement(data, element, elementsOrder);
236: } else {
237: data.appendChild(element);
238: }
239: }
240: }
241: }
242: antProjectHelper.putPrimaryConfigurationData(data, true);
243: }
244:
245: /**
246: * Find all direct child elements of an element.
247: * More useful than {@link Element#getElementsByTagNameNS} because it does
248: * not recurse into recursive child elements.
249: * Children which are all-whitespace text nodes are ignored; others cause
250: * an exception to be thrown.
251: * @param parent a parent element in a DOM tree
252: * @return a list of direct child elements (may be empty)
253: * @throws IllegalArgumentException if there are non-element children besides whitespace
254: */
255: private static List<Element> findSubElements(Element parent) {
256: NodeList l = parent.getChildNodes();
257: List<Element> elements = new ArrayList<Element>(l.getLength());
258: for (int i = 0; i < l.getLength(); i++) {
259: Node n = l.item(i);
260: if (n.getNodeType() == Node.ELEMENT_NODE) {
261: elements.add((Element) n);
262: } else if (n.getNodeType() == Node.TEXT_NODE) {
263: String text = ((Text) n).getNodeValue();
264: if (text.trim().length() > 0) {
265: throw new IllegalArgumentException(
266: "non-ws text encountered in " + parent
267: + ": " + text);
268: }
269: } else if (n.getNodeType() == Node.COMMENT_NODE) {
270: // skip
271: } else {
272: throw new IllegalArgumentException(
273: "unexpected non-element child of " + parent
274: + ": " + n);
275: }
276: }
277: return elements;
278: }
279:
280: /**
281: * Append child element to the correct position according to given
282: * order.
283: * @param parent parent to which the child will be added
284: * @param el element to be added
285: * @param order order of the elements which must be followed
286: */
287: private static void appendChildElement(Element parent, Element el,
288: String[] order) {
289: Element insertBefore = null;
290: List l = Arrays.asList(order);
291: int index = l.indexOf(el.getLocalName());
292: assert index != -1 : el.getLocalName() + " was not found in "
293: + l;
294: Iterator it = findSubElements(parent).iterator();
295: while (it.hasNext()) {
296: Element e = (Element) it.next();
297: int index2 = l.indexOf(e.getLocalName());
298: assert index2 != -1 : e.getLocalName()
299: + " was not found in " + l;
300: if (index2 > index) {
301: insertBefore = e;
302: break;
303: }
304: }
305: parent.insertBefore(el, insertBefore);
306: }
307:
308: private Element createLibraryElement(Document doc, String pathItem,
309: Item item, String libraryElementName) {
310: Element libraryElement = doc.createElementNS(
311: projectConfigurationNameSpace, libraryElementName);
312: List<File> files = new ArrayList<File>();
313: List<File> dirs = new ArrayList<File>();
314: getFilesForItem(item, files, dirs);
315: if (files.size() > 0) {
316: libraryElement.setAttribute(ATTR_FILES, "" + files.size()); // NOI18N
317: }
318: if (dirs.size() > 0) {
319: libraryElement.setAttribute(ATTR_DIRS, "" + dirs.size()); // NOI18N
320: }
321: libraryElement.appendChild(doc.createTextNode(pathItem));
322: return libraryElement;
323: }
324:
325: public static final class Item extends BaseClassPathSupport.Item {
326: private boolean includedInDeployment;
327:
328: Item(
329: org.netbeans.modules.java.api.common.classpath.ClassPathSupport.Item delegate,
330: String property, boolean includedInDeployment,
331: String raw) {
332: super (delegate, property, raw);
333: this .includedInDeployment = includedInDeployment;
334: }
335:
336: public static Item create(Library library, String property,
337: boolean included) {
338: org.netbeans.modules.java.api.common.classpath.ClassPathSupport.Item delegate = org.netbeans.modules.java.api.common.classpath.ClassPathSupport.Item
339: .create(library, property);
340: String libraryName = library.getName();
341: return new Item(delegate, property, included, "${libs."
342: + libraryName + ".classpath}"); // NOI18N
343: }
344:
345: public static Item create(AntArtifact artifact,
346: URI artifactURI, String property, boolean included) {
347: org.netbeans.modules.java.api.common.classpath.ClassPathSupport.Item delegate = org.netbeans.modules.java.api.common.classpath.ClassPathSupport.Item
348: .create(artifact, artifactURI, property);
349: return new Item(delegate, property, included, null);
350: }
351:
352: public static Item create(File file, String property,
353: boolean included) {
354: org.netbeans.modules.java.api.common.classpath.ClassPathSupport.Item delegate = org.netbeans.modules.java.api.common.classpath.ClassPathSupport.Item
355: .create(file, property);
356: return new Item(delegate, property, included, null);
357: }
358:
359: public static Item create(String property, boolean included) {
360: org.netbeans.modules.java.api.common.classpath.ClassPathSupport.Item delegate = org.netbeans.modules.java.api.common.classpath.ClassPathSupport.Item
361: .create(property);
362: return new Item(delegate, property, included, null);
363: }
364:
365: public static Item createBroken(ClassPathItem.Type type,
366: String property, boolean included) {
367: org.netbeans.modules.java.api.common.classpath.ClassPathSupport.Item delegate = org.netbeans.modules.java.api.common.classpath.ClassPathSupport.Item
368: .createBroken(type, property);
369: return new Item(delegate, property, included, null);
370: }
371:
372: public static Item createBroken(File file, String property,
373: boolean included) {
374: org.netbeans.modules.java.api.common.classpath.ClassPathSupport.Item delegate = org.netbeans.modules.java.api.common.classpath.ClassPathSupport.Item
375: .createBroken(file, property);
376: return new Item(delegate, property, included, null);
377: }
378:
379: public boolean isIncludedInDeployment() {
380: // boolean result = includedInDeployment;
381: // if (getType() == TYPE_JAR) {
382: // at the moment we can't include folders in deployment
383: // FileObject fo = FileUtil.toFileObject(getFile());
384: // if (fo == null || fo.isFolder())
385: // return false;
386: // }
387: return includedInDeployment;
388: }
389:
390: public void setIncludedInDeployment(boolean includedInDeployment) {
391: this .includedInDeployment = includedInDeployment;
392: }
393:
394: @Override
395: public String toString() {
396: StringBuilder sb = new StringBuilder(200);
397: sb.append(delegate.toString());
398: sb.append(", raw = "); // NOI18N
399: sb.append(getRaw());
400: sb.append(", includedInDeployment = "); // NOI18N
401: sb.append(includedInDeployment);
402: return sb.toString();
403: }
404: }
405: }
|