001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM - Initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.internal.build;
011:
012: import java.io.*;
013: import java.net.MalformedURLException;
014: import java.net.URL;
015: import java.util.*;
016: import org.eclipse.core.runtime.*;
017: import org.eclipse.osgi.service.resolver.BundleDescription;
018: import org.eclipse.osgi.util.NLS;
019: import org.eclipse.pde.internal.build.ant.AntScript;
020: import org.eclipse.update.core.IFeature;
021: import org.eclipse.update.core.IPluginEntry;
022: import org.osgi.framework.Version;
023:
024: /**
025: * General utility class.
026: */
027: public final class Utils implements IPDEBuildConstants,
028: IBuildPropertiesConstants, IXMLConstants {
029: /**
030: * Convert a list of tokens into an array. The list separator has to be
031: * specified.
032: */
033: public static String[] getArrayFromString(String list,
034: String separator) {
035: if (list == null || list.trim().equals("")) //$NON-NLS-1$
036: return new String[0];
037: List result = new ArrayList();
038: for (StringTokenizer tokens = new StringTokenizer(list,
039: separator); tokens.hasMoreTokens();) {
040: String token = tokens.nextToken().trim();
041: if (!token.equals("")) //$NON-NLS-1$
042: result.add(token);
043: }
044: return (String[]) result.toArray(new String[result.size()]);
045: }
046:
047: /**
048: * Convert a list of tokens into an array. The list separator has to be
049: * specified. The spcecificity of this method is that it returns an empty
050: * element when to same separators are following each others. For example
051: * the string a,,b returns the following array [a, ,b]
052: *
053: */
054: public static String[] getArrayFromStringWithBlank(String list,
055: String separator) {
056: if (list == null || list.trim().length() == 0)
057: return new String[0];
058: List result = new ArrayList();
059: boolean previousWasSeparator = true;
060: for (StringTokenizer tokens = new StringTokenizer(list,
061: separator, true); tokens.hasMoreTokens();) {
062: String token = tokens.nextToken().trim();
063: if (token.equals(separator)) {
064: if (previousWasSeparator)
065: result.add(""); //$NON-NLS-1$
066: previousWasSeparator = true;
067: } else {
068: result.add(token);
069: previousWasSeparator = false;
070: }
071: }
072: return (String[]) result.toArray(new String[result.size()]);
073: }
074:
075: /**
076: * Return a string array constructed from the given list of comma-separated
077: * tokens.
078: *
079: * @param list
080: * the list to convert
081: * @return the array of strings
082: */
083: public static String[] getArrayFromString(String list) {
084: return getArrayFromString(list, ","); //$NON-NLS-1$
085: }
086:
087: /**
088: * Converts an array of strings into an array of URLs.
089: *
090: * @param target
091: * @return URL[]
092: * @throws CoreException
093: */
094: public static URL[] asURL(String[] target) throws CoreException {
095: if (target == null)
096: return null;
097: try {
098: URL[] result = new URL[target.length];
099: for (int i = 0; i < target.length; i++)
100: result[i] = new URL(target[i]);
101: return result;
102: } catch (MalformedURLException e) {
103: throw new CoreException(new Status(IStatus.ERROR,
104: PI_PDEBUILD, EXCEPTION_MALFORMED_URL, e
105: .getMessage(), e));
106: }
107: }
108:
109: public static URL[] asURL(Collection target) throws CoreException {
110: if (target == null)
111: return null;
112: try {
113: URL[] result = new URL[target.size()];
114: int i = 0;
115: for (Iterator iter = target.iterator(); iter.hasNext();) {
116: result[i++] = ((File) iter.next()).toURL();
117: }
118: return result;
119: } catch (MalformedURLException e) {
120: throw new CoreException(new Status(IStatus.ERROR,
121: PI_PDEBUILD, EXCEPTION_MALFORMED_URL, e
122: .getMessage(), e));
123: }
124: }
125:
126: public static File[] asFile(String[] target) {
127: if (target == null)
128: return new File[0];
129: File[] result = new File[target.length];
130: for (int i = 0; i < result.length; i++) {
131: result[i] = new File(target[i]);
132: }
133: return result;
134: }
135:
136: public static File[] asFile(URL[] target) {
137: if (target == null)
138: return new File[0];
139: File[] result = new File[target.length];
140: for (int i = 0; i < result.length; i++) {
141: result[i] = new File(target[i].getFile());
142: }
143: return result;
144: }
145:
146: /**
147: * Return a string which is a concatination of each member of the given
148: * collection, separated by the given separator.
149: *
150: * @param collection
151: * the collection to concatinate
152: * @param separator
153: * the separator to use
154: * @return String
155: */
156: public static String getStringFromCollection(Collection collection,
157: String separator) {
158: StringBuffer result = new StringBuffer();
159: boolean first = true;
160: for (Iterator i = collection.iterator(); i.hasNext();) {
161: if (first)
162: first = false;
163: else
164: result.append(separator);
165: result.append(i.next());
166: }
167: return result.toString();
168: }
169:
170: /**
171: * Return a string which is a concatination of each member of the given
172: * array, separated by the given separator.
173: *
174: * @param values
175: * the array to concatinate
176: * @param separator
177: * the separator to use
178: * @return String
179: */
180: public static String getStringFromArray(String[] values,
181: String separator) {
182: StringBuffer result = new StringBuffer();
183: for (int i = 0; i < values.length; i++) {
184: if (values[i] != null) {
185: if (i > 0)
186: result.append(separator);
187: result.append(values[i]);
188: }
189: }
190: return result.toString();
191: }
192:
193: /**
194: * Return a path which is equivalent to the given location relative to the
195: * specified base path.
196: *
197: * @param location
198: * the location to convert
199: * @param base
200: * the base path
201: * @return IPath
202: */
203: public static IPath makeRelative(IPath location, IPath base) {
204: //can't make relative if the devices don't match
205: if (location.getDevice() == null) {
206: if (base.getDevice() != null)
207: return location;
208: } else {
209: if (!location.getDevice()
210: .equalsIgnoreCase(base.getDevice()))
211: return location;
212: }
213: int baseCount = base.segmentCount();
214: int count = base.matchingFirstSegments(location);
215: String temp = ""; //$NON-NLS-1$
216: for (int j = 0; j < baseCount - count; j++)
217: temp += "../"; //$NON-NLS-1$
218: return new Path(temp).append(location
219: .removeFirstSegments(count));
220: }
221:
222: /**
223: * Transfers all available bytes from the given input stream to the given
224: * output stream. Regardless of failure, this method closes both streams.
225: *
226: * @param source
227: * @param destination
228: * @throws IOException
229: */
230: public static void transferStreams(InputStream source,
231: OutputStream destination) throws IOException {
232: source = new BufferedInputStream(source);
233: destination = new BufferedOutputStream(destination);
234: try {
235: byte[] buffer = new byte[8192];
236: while (true) {
237: int bytesRead = -1;
238: if ((bytesRead = source.read(buffer)) == -1)
239: break;
240: destination.write(buffer, 0, bytesRead);
241: }
242: } finally {
243: try {
244: source.close();
245: } catch (IOException e) {
246: // ignore
247: }
248: try {
249: destination.close();
250: } catch (IOException e) {
251: // ignore
252: }
253: }
254: }
255:
256: public static IPluginEntry[] getPluginEntry(IFeature feature,
257: String pluginId, boolean raw) {
258: IPluginEntry[] plugins;
259: if (raw)
260: plugins = feature.getRawPluginEntries();
261: else
262: plugins = feature.getPluginEntries();
263: List foundEntries = new ArrayList(5);
264:
265: for (int i = 0; i < plugins.length; i++) {
266: if (plugins[i].getVersionedIdentifier().getIdentifier()
267: .equals(pluginId))
268: foundEntries.add(plugins[i]);
269: }
270: return (IPluginEntry[]) foundEntries
271: .toArray(new IPluginEntry[foundEntries.size()]);
272:
273: }
274:
275: // Return a collection of File, the result can be null
276: public static Collection findFiles(File from, String foldername,
277: final String filename) {
278: // if from is a file which name match filename, then simply return the
279: // file
280: File root = from;
281: if (root.isFile() && root.getName().equals(filename)) {
282: Collection coll = new ArrayList(1);
283: coll.add(root);
284: return coll;
285: }
286:
287: Collection collectedElements = new ArrayList(10);
288:
289: File[] featureDirectoryContent = new File(from, foldername)
290: .listFiles();
291: if (featureDirectoryContent == null)
292: return null;
293:
294: for (int i = 0; i < featureDirectoryContent.length; i++) {
295: if (featureDirectoryContent[i].isDirectory()) {
296: File[] featureFiles = featureDirectoryContent[i]
297: .listFiles(new FilenameFilter() {
298: public boolean accept(File dir, String name) {
299: return name.equals(filename);
300: }
301: });
302: if (featureFiles.length != 0)
303: collectedElements.add(featureFiles[0]);
304: }
305: }
306: return collectedElements;
307: }
308:
309: public static boolean isIn(IPluginEntry[] array,
310: IPluginEntry element) {
311: for (int i = 0; i < array.length; i++) {
312: if (array[i].getVersionedIdentifier().equals(
313: element.getVersionedIdentifier()))
314: return true;
315: }
316: return false;
317: }
318:
319: public static Collection copyFiles(String fromDir, String toDir)
320: throws CoreException {
321: File templateLocation = new File(fromDir);
322: Collection copiedFiles = new ArrayList();
323: if (templateLocation.exists()) {
324: File[] files = templateLocation.listFiles();
325: if (files != null) {
326: for (int i = 0; i < files.length; i++) {
327: if (files[i].isDirectory()) {
328: File subDir = new File(toDir, files[i]
329: .getName());
330: if (!subDir.exists())
331: subDir.mkdirs();
332: Collection subFiles = copyFiles(fromDir + '/'
333: + files[i].getName(), toDir + '/'
334: + files[i].getName());
335: for (Iterator iter = subFiles.iterator(); iter
336: .hasNext();) {
337: String sub = (String) iter.next();
338: copiedFiles.add(files[i].getName() + '/'
339: + sub);
340: }
341: continue;
342: }
343:
344: FileInputStream inputStream = null;
345: FileOutputStream outputStream = null;
346:
347: try {
348: inputStream = new FileInputStream(files[i]);
349: } catch (FileNotFoundException e) {
350: String message = NLS.bind(
351: Messages.exception_missingFile,
352: files[i].getAbsolutePath());
353: throw new CoreException(new Status(
354: IStatus.ERROR, PI_PDEBUILD,
355: EXCEPTION_READING_FILE, message, e));
356: }
357:
358: String fileToCopy = toDir + '/'
359: + files[i].getName();
360: try {
361: outputStream = new FileOutputStream(fileToCopy);
362: } catch (FileNotFoundException e) {
363: String message = NLS.bind(
364: Messages.exception_missingFile,
365: fileToCopy);
366: throw new CoreException(new Status(
367: IStatus.ERROR, PI_PDEBUILD,
368: EXCEPTION_READING_FILE, message, e));
369: }
370:
371: try {
372: Utils
373: .transferStreams(inputStream,
374: outputStream);
375: copiedFiles.add(files[i].getName());
376: } catch (IOException e) {
377: String message = NLS.bind(
378: Messages.exception_writingFile,
379: fileToCopy);
380: throw new CoreException(new Status(
381: IStatus.ERROR, PI_PDEBUILD,
382: EXCEPTION_WRITING_FILE, message, e));
383: }
384: }
385: }
386: }
387: return copiedFiles;
388: }
389:
390: public static List extractPlugins(List initialList, List toExtract) {
391: //TODO This algorithm needs to be improved
392: if (initialList.size() == toExtract.size())
393: return initialList;
394: List result = new ArrayList(toExtract.size());
395: for (Iterator iter = initialList.iterator(); iter.hasNext();) {
396: Object element = iter.next();
397: if (toExtract.contains(element)) {
398: result.add(element);
399: if (result.size() == toExtract.size())
400: break;
401: }
402: }
403: return result;
404: }
405:
406: public static int isStringIn(String[] searched, String toSearch) {
407: if (searched == null || toSearch == null)
408: return -1;
409: for (int i = 0; i < searched.length; i++) {
410: if (toSearch.startsWith(searched[i]))
411: return i;
412: }
413: return -1;
414: }
415:
416: public static void generatePermissions(
417: Properties featureProperties, Config aConfig,
418: String targetRootProperty, AntScript script) {
419: String configInfix = aConfig.toString("."); //$NON-NLS-1$
420: String configPath = aConfig.toStringReplacingAny(".",
421: ANY_STRING);
422: String prefixPermissions = ROOT_PREFIX + configInfix + '.'
423: + PERMISSIONS + '.';
424: String prefixLinks = ROOT_PREFIX + configInfix + '.' + LINK;
425: String commonPermissions = ROOT_PREFIX + PERMISSIONS + '.';
426: String commonLinks = ROOT_PREFIX + LINK;
427: for (Iterator iter = featureProperties.entrySet().iterator(); iter
428: .hasNext();) {
429: Map.Entry permission = (Map.Entry) iter.next();
430: String instruction = (String) permission.getKey();
431: String parameters = removeEndingSlashes((String) permission
432: .getValue());
433: if (instruction.startsWith(prefixPermissions)) {
434: generateChmodInstruction(
435: script,
436: getPropertyFormat(targetRootProperty)
437: + '/'
438: + configPath
439: + '/'
440: + getPropertyFormat(PROPERTY_COLLECTING_FOLDER),
441: instruction.substring(prefixPermissions
442: .length()), parameters);
443: continue;
444: }
445: if (instruction.startsWith(prefixLinks)) {
446: generateLinkInstruction(
447: script,
448: getPropertyFormat(targetRootProperty)
449: + '/'
450: + configPath
451: + '/'
452: + getPropertyFormat(PROPERTY_COLLECTING_FOLDER),
453: parameters);
454: continue;
455: }
456: if (instruction.startsWith(commonPermissions)) {
457: generateChmodInstruction(
458: script,
459: getPropertyFormat(targetRootProperty)
460: + '/'
461: + configPath
462: + '/'
463: + getPropertyFormat(PROPERTY_COLLECTING_FOLDER),
464: instruction.substring(commonPermissions
465: .length()), parameters);
466: continue;
467: }
468: if (instruction.startsWith(commonLinks)) {
469: generateLinkInstruction(
470: script,
471: getPropertyFormat(targetRootProperty)
472: + '/'
473: + configPath
474: + '/'
475: + getPropertyFormat(PROPERTY_COLLECTING_FOLDER),
476: parameters);
477: continue;
478: }
479: }
480: }
481:
482: public static String removeEndingSlashes(String value) {
483: String[] params = Utils.getArrayFromString(value, ","); //$NON-NLS-1$
484: for (int i = 0; i < params.length; i++) {
485: if (params[i].endsWith("/")) //$NON-NLS-1$
486: params[i] = params[i].substring(0,
487: params[i].length() - 1);
488: }
489: return Utils.getStringFromArray(params, ","); //$NON-NLS-1$
490: }
491:
492: private static void generateChmodInstruction(AntScript script,
493: String dir, String rights, String files) {
494: if (rights.equals(EXECUTABLE)) {
495: rights = "755"; //$NON-NLS-1$
496: }
497: script.printChmod(dir, rights, files);
498: }
499:
500: private static void generateLinkInstruction(AntScript script,
501: String dir, String files) {
502: String[] links = Utils.getArrayFromString(files, ","); //$NON-NLS-1$
503: List arguments = new ArrayList(2);
504: for (int i = 0; i < links.length; i += 2) {
505: arguments.add("-sf"); //$NON-NLS-1$
506: arguments.add(links[i]);
507: arguments.add(links[i + 1]);
508: script.printExecTask("ln", dir, arguments, "Linux"); //$NON-NLS-1$ //$NON-NLS-2$
509: arguments.clear();
510: }
511: }
512:
513: /**
514: * Return a string with the given property name in the format:
515: * <pre>${propertyName}</pre>.
516: *
517: * @param propertyName the name of the property
518: * @return String
519: */
520: public static String getPropertyFormat(String propertyName) {
521: StringBuffer sb = new StringBuffer();
522: sb.append(PROPERTY_ASSIGNMENT_PREFIX);
523: sb.append(propertyName);
524: sb.append(PROPERTY_ASSIGNMENT_SUFFIX);
525: return sb.toString();
526: }
527:
528: public static boolean isBinary(BundleDescription bundle) {
529: Properties bundleProperties = ((Properties) bundle
530: .getUserObject());
531: if (bundleProperties == null
532: || bundleProperties.get(IS_COMPILED) == null) {
533: File props = new File(bundle.getLocation(), PROPERTIES_FILE);
534: return !(props.exists() && props.isFile());
535: }
536: return (Boolean.FALSE == bundleProperties.get(IS_COMPILED));
537: }
538:
539: public static Object[] parseExtraBundlesString(String input,
540: boolean onlyId) {
541: StringTokenizer tokenizer = null;
542: if (onlyId)
543: tokenizer = new StringTokenizer(
544: input.startsWith("plugin@") ? input.substring(7) : input.substring(8), ";"); //$NON-NLS-1$//$NON-NLS-2$
545: else
546: tokenizer = new StringTokenizer(input, ";"); //$NON-NLS-1$
547: String bundleId = tokenizer.nextToken();
548: Version version = Version.emptyVersion;
549: Boolean unpack = Boolean.FALSE;
550: while (tokenizer.hasMoreTokens()) {
551: String token = tokenizer.nextToken();
552: if (token.startsWith("version")) { //$NON-NLS-1$
553: version = new Version(token.substring(8));
554: continue;
555: }
556: if (token.startsWith("unpack")) { //$NON-NLS-1$
557: unpack = (token.toLowerCase().indexOf(TRUE) > -1) ? Boolean.TRUE
558: : Boolean.FALSE;
559: continue;
560: }
561: }
562: return new Object[] { bundleId, version, unpack };
563: }
564:
565: }
|