001: /**********************************************************************
002: * Copyright (c) 2000, 2006 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 Corporation - initial API and implementation
010: * Gunnar Wagenknecht - adaption to new fetch script builder API
011: **********************************************************************/package org.eclipse.pde.internal.build.fetch;
012:
013: import java.util.*;
014: import org.eclipse.core.runtime.*;
015: import org.eclipse.osgi.util.NLS;
016: import org.eclipse.pde.build.*;
017: import org.eclipse.pde.internal.build.*;
018:
019: /**
020: * An <code>FetchTaskFactory</code> for building fetch scripts that will
021: * fetch content from a CVS repository (id: <code>CVS</code>).
022: * <p>
023: * <code><pre>
024: * Map file format:
025: * type@id,[version]=CVS,args
026: * args is a comma-separated list of key/value pairs
027: * Accepted args include:
028: * cvsPassFile - optional password file
029: * cvsRoot - mandatory repo location
030: * password - optional password
031: * path - optional path relative to the cvsRoot
032: * prebuilt - optional boolean value indicating that the entry points to a pre-built bundle in the repository
033: * tag - mandatory CVS tag
034: * </pre></code>
035: * </p>
036: */
037: public class CVSFetchTaskFactory implements IFetchFactory {
038: public static final String ID = "CVS"; //$NON-NLS-1$
039:
040: private static final String TARGET_GET_FROM_CVS = "FetchFromCVS"; //$NON-NLS-1$
041: private static final String SEPARATOR = ","; //$NON-NLS-1$
042: public static final String OVERRIDE_TAG = ID;
043:
044: //CVS specific keys used in the map being passed around.
045: private static final String KEY_CVSROOT = "cvsRoot"; //$NON-NLS-1$
046: private static final String KEY_CVSPASSFILE = "cvsPassFile"; //$NON-NLS-1$
047: private static final String KEY_PASSWORD = "password"; //$NON-NLS-1$
048: private static final String KEY_PATH = "path"; //$NON-NLS-1$
049: private static final String KEY_PREBUILT = "prebuilt"; //$NON-NLS-1$
050:
051: //Properties used in the CVS part of the scripts
052: private static final String PROP_DESTINATIONFOLDER = "destinationFolder"; //$NON-NLS-1$
053: private static final String PROP_CVSROOT = "cvsRoot"; //$NON-NLS-1$
054: private static final String PROP_MODULE = "module"; //$NON-NLS-1$
055: private static final String PROP_TAG = "tag"; //$NON-NLS-1$
056: private static final String PROP_QUIET = "quiet"; //$NON-NLS-1$
057: private static final String PROP_FILETOCHECK = "fileToCheck"; //$NON-NLS-1$
058: private static final String PROP_ELEMENTNAME = "elementName"; //$NON-NLS-1$
059:
060: private void generateAuthentificationAntTask(Map entryInfos,
061: IAntScript script) {
062: String password = (String) entryInfos.get(KEY_PASSWORD);
063: String cvsPassFileLocation = (String) entryInfos
064: .get(KEY_CVSPASSFILE);
065: if (password != null)
066: printCVSPassTask((String) entryInfos.get(KEY_CVSROOT),
067: password, cvsPassFileLocation, script);
068: }
069:
070: public void generateRetrieveElementCall(Map entryInfos,
071: IPath destination, IAntScript script) {
072: String type = (String) entryInfos.get(KEY_ELEMENT_TYPE);
073: String element = (String) entryInfos.get(KEY_ELEMENT_NAME);
074: boolean prebuilt = "true".equalsIgnoreCase((String) entryInfos
075: .get(KEY_PREBUILT));
076:
077: Map params = new HashMap(5);
078: // we directly export the CVS content into the destination. if we have a pre-built JAR then
079: // we want to put it right in the /plugins directory and not a sub-directory so strip off 2 segments
080: // to leave us with the build directory (/plugins will be added by the "element" attribute)
081: int remove = prebuilt ? 2 : 1;
082: String suggestedPath = destination.lastSegment();
083: params.put(PROP_DESTINATIONFOLDER, destination
084: .removeLastSegments(remove).toString());
085: params.put(PROP_TAG, entryInfos
086: .get(IFetchFactory.KEY_ELEMENT_TAG));
087: params.put(PROP_CVSROOT, entryInfos.get(KEY_CVSROOT));
088: params.put(PROP_QUIET, "${cvs.quiet}"); //$NON-NLS-1$
089: // the call to CVS requires us to pass a destination directory for the files that we are
090: // retrieving, so give it the /plugins dir here
091: if (prebuilt) {
092: if (type.equals(ELEMENT_TYPE_PLUGIN))
093: element = IPDEBuildConstants.DEFAULT_PLUGIN_LOCATION;
094: else if (type.equals(ELEMENT_TYPE_FEATURE))
095: element = IPDEBuildConstants.DEFAULT_FEATURE_LOCATION;
096: } else {
097: if (suggestedPath != null)
098: element = suggestedPath;
099: }
100: params.put(PROP_ELEMENTNAME, element);
101: String module = entryInfos.get(KEY_PATH) == null ? element
102: : (String) entryInfos.get(KEY_PATH);
103: params.put(PROP_MODULE, module);
104:
105: IPath locationToCheck = (IPath) destination.clone();
106: // if we have a pre-built plug-in then we want to check the existence of the JAR file
107: // rather than the plug-in manifest.
108: if (prebuilt) {
109: locationToCheck = locationToCheck.removeLastSegments(1);
110: locationToCheck = locationToCheck.append(new Path(module)
111: .lastSegment());
112: } else {
113: if (type.equals(ELEMENT_TYPE_FEATURE)) {
114: locationToCheck = locationToCheck
115: .append(Constants.FEATURE_FILENAME_DESCRIPTOR);
116: } else if (type.equals(ELEMENT_TYPE_PLUGIN)) {
117: locationToCheck = locationToCheck
118: .append(Constants.PLUGIN_FILENAME_DESCRIPTOR);
119: } else if (type.equals(ELEMENT_TYPE_FRAGMENT)) {
120: locationToCheck = locationToCheck
121: .append(Constants.FRAGMENT_FILENAME_DESCRIPTOR);
122: } else if (type.equals(ELEMENT_TYPE_BUNDLE)) {
123: locationToCheck = locationToCheck
124: .append(Constants.BUNDLE_FILENAME_DESCRIPTOR);
125: }
126: }
127: params.put(PROP_FILETOCHECK, locationToCheck.toString());
128:
129: printAvailableTask(locationToCheck.toString(), locationToCheck
130: .toString(), script);
131: if (!prebuilt
132: && (type.equals(IFetchFactory.ELEMENT_TYPE_PLUGIN) || type
133: .equals(IFetchFactory.ELEMENT_TYPE_FRAGMENT))) {
134: printAvailableTask(locationToCheck.toString(),
135: locationToCheck.removeLastSegments(1).append(
136: Constants.BUNDLE_FILENAME_DESCRIPTOR)
137: .toString(), script);
138: }
139:
140: generateAuthentificationAntTask(entryInfos, script);
141: script.printAntCallTask(TARGET_GET_FROM_CVS, true, params);
142: }
143:
144: public void generateRetrieveFilesCall(final Map entryInfos,
145: IPath destination, final String[] files, IAntScript script) {
146: generateAuthentificationAntTask(entryInfos, script);
147: String path = (String) entryInfos.get(KEY_PATH);
148: for (int i = 0; i < files.length; i++) {
149: String file = files[i];
150: IPath filePath;
151: if (path != null) {
152: filePath = new Path(path).append(file);
153: } else {
154: filePath = new Path((String) entryInfos
155: .get(KEY_ELEMENT_NAME)).append(file);
156: }
157: String tag = (String) entryInfos
158: .get(IFetchFactory.KEY_ELEMENT_TAG);
159: String cvsRoot = (String) entryInfos.get(KEY_CVSROOT);
160: String dest = "true".equalsIgnoreCase((String) entryInfos.get(KEY_PREBUILT)) ? destination.removeLastSegments(1).toString() : destination.toString(); //$NON-NLS-1$
161: printCVSTask(
162: "export -r " + tag + ' ' + filePath.toString(), cvsRoot, dest, null, null, "true", null, null, "${fetch.failonerror}", script); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
163: script
164: .println("<move file=\"" + destination + '/' + filePath + "\"" + " tofile=\"" + destination.append(file) + "\" failonerror=\"false\" />"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
165: }
166: }
167:
168: public void addTargets(IAntScript script) {
169: script.printTargetDeclaration(TARGET_GET_FROM_CVS, null, null,
170: "${fileToCheck}", null); //$NON-NLS-1$
171: printCVSTask(
172: "export -d ${" + PROP_ELEMENTNAME + "}", "${" + PROP_CVSROOT + "}", "${" + PROP_DESTINATIONFOLDER + "}", "${" + PROP_MODULE + "}", "${" + PROP_TAG + "}", "${" + PROP_QUIET + "}", null, "CVS - ${" + PROP_MODULE + "}", script); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$ //$NON-NLS-13$ //$NON-NLS-14$
173: script.printTargetEnd();
174: }
175:
176: /*
177: * Handle the old file format:
178: * Map file arguments:
179: * <code><TAG>,<CVSROOT>[,<PASSWORD>[,<PATH>[,<CVSPASSFILE>]]]</code>
180: */
181: private void legacyParseMapFileEntry(String[] arguments,
182: Properties overrideTags, Map entryInfos) {
183: String overrideTag = overrideTags != null ? overrideTags
184: .getProperty(OVERRIDE_TAG) : null;
185: entryInfos
186: .put(KEY_CVSPASSFILE,
187: (arguments.length > 4 && !arguments[4]
188: .equals("")) ? arguments[4] : null); //$NON-NLS-1$
189: entryInfos
190: .put(
191: IFetchFactory.KEY_ELEMENT_TAG,
192: (overrideTag != null
193: && overrideTag.trim().length() != 0 ? overrideTag
194: : arguments[0]));
195: entryInfos.put(KEY_CVSROOT, arguments[1]);
196: entryInfos
197: .put(KEY_PASSWORD,
198: (arguments.length > 2 && !arguments[2]
199: .equals("")) ? arguments[2] : null); //$NON-NLS-1$
200: entryInfos.put(KEY_PATH, (arguments.length > 3 && !arguments[3]
201: .equals("")) ? arguments[3] : null); //$NON-NLS-1$
202: }
203:
204: public void parseMapFileEntry(String repoSpecificentry,
205: Properties overrideTags, Map entryInfos)
206: throws CoreException {
207: String[] arguments = Utils.getArrayFromStringWithBlank(
208: repoSpecificentry, SEPARATOR);
209: if (arguments.length < 2) {
210: String message = NLS.bind(
211: Messages.error_incorrectDirectoryEntry, entryInfos
212: .get(KEY_ELEMENT_NAME));
213: throw new CoreException(new Status(IStatus.ERROR,
214: IPDEBuildConstants.PI_PDEBUILD, 1, message, null)); //TODO Need to fix this
215: }
216:
217: // build up the table of arguments in the map file entry
218: Map table = new HashMap();
219: for (int i = 0; i < arguments.length; i++) {
220: String arg = arguments[i];
221: // if we have at least one arg without an equals sign, then
222: // revert back to the legacy parsing
223: int index = arg.indexOf('=');
224: if (index == -1) {
225: legacyParseMapFileEntry(arguments, overrideTags,
226: entryInfos);
227: return;
228: }
229: String key = arg.substring(0, index);
230: String value = arg.substring(index + 1);
231: table.put(key, value);
232: }
233:
234: // add entries to the entryInfo map here instead of inside the loop
235: // in case we revert to legacy parsing in the middle of the loop (we
236: // don't want to contaminate entryInfos
237: entryInfos.put(KEY_CVSPASSFILE, table.get(KEY_CVSPASSFILE));
238: String overrideTag = overrideTags != null ? overrideTags
239: .getProperty(OVERRIDE_TAG) : null;
240: entryInfos
241: .put(
242: IFetchFactory.KEY_ELEMENT_TAG,
243: (overrideTag != null
244: && overrideTag.trim().length() != 0 ? overrideTag
245: : table
246: .get(IFetchFactory.KEY_ELEMENT_TAG)));
247: entryInfos.put(KEY_CVSROOT, table.get(KEY_CVSROOT));
248: entryInfos.put(KEY_PASSWORD, table.get(KEY_PASSWORD));
249: entryInfos.put(KEY_PATH, table.get(KEY_PATH));
250: entryInfos.put(KEY_PREBUILT, table.get(KEY_PREBUILT));
251: }
252:
253: /**
254: * Print a <code>cvs</code> task to the Ant script.
255: *
256: * @param command the CVS command to run
257: * @param cvsRoot value for the CVSROOT variable
258: * @param dest the destination directory for the checked out resources
259: * @param module the module name to check out
260: * @param tag the tag of the module to check out
261: * @param quiet whether or not to print informational messages to the output
262: * @param passFile the name of the password file
263: */
264: private void printCVSTask(String command, String cvsRoot,
265: String dest, String module, String tag, String quiet,
266: String passFile, String taskname, IAntScript script) {
267: printCVSTask(command, cvsRoot, dest, module, tag, quiet,
268: passFile, taskname, null, script);
269: }
270:
271: /**
272: * Print a <code>cvs</code> task to the Ant script.
273: *
274: * @param command the CVS command to run
275: * @param cvsRoot value for the CVSROOT variable
276: * @param dest the destination directory for the checked out resources
277: * @param module the module name to check out
278: * @param tag the tag of the module to check out
279: * @param quiet whether or not to print informational messages to the output
280: * @param passFile the name of the password file
281: * @param failOnError whether or not to throw an exception if something goes wrong
282: */
283: private void printCVSTask(String command, String cvsRoot,
284: String dest, String module, String tag, String quiet,
285: String passFile, String taskname, String failOnError,
286: IAntScript script) {
287: script.printTabs();
288: script.print("<cvs"); //$NON-NLS-1$
289: script.printAttribute("command", command, false); //$NON-NLS-1$
290: script.printAttribute("cvsRoot", cvsRoot, false); //$NON-NLS-1$
291: script.printAttribute("dest", dest, false); //$NON-NLS-1$
292: script.printAttribute("package", module, false); //$NON-NLS-1$
293: script.printAttribute("tag", tag, false); //$NON-NLS-1$
294: script.printAttribute("quiet", quiet, false); //$NON-NLS-1$
295: script.printAttribute("passfile", passFile, false); //$NON-NLS-1$
296: script.printAttribute("taskname", taskname, false); //$NON-NLS-1$
297: script.printAttribute("failonerror", failOnError, false); //$NON-NLS-1$
298: script.println("/>"); //$NON-NLS-1$
299: }
300:
301: /**
302: * Print a <code>cvspass</code> task to the Ant script.
303: *
304: * @param cvsRoot the name of the repository
305: * @param password the password
306: * @param passFile the name of the password file
307: */
308: private void printCVSPassTask(String cvsRoot, String password,
309: String passFile, IAntScript script) {
310: script.printTabs();
311: script.print("<cvspass"); //$NON-NLS-1$
312: script.printAttribute("cvsRoot", cvsRoot, true); //$NON-NLS-1$
313: script.printAttribute("password", password, true); //$NON-NLS-1$
314: script.printAttribute("passfile", passFile, false); //$NON-NLS-1$
315: script.println("/>"); //$NON-NLS-1$
316: }
317:
318: /**
319: * Print the <code>available</code> Ant task to this script. This task sets a property
320: * value if the given file exists at runtime.
321: *
322: * @param property the property to set
323: * @param file the file to look for
324: */
325: private void printAvailableTask(String property, String file,
326: IAntScript script) {
327: script.printTabs();
328: script.print("<available"); //$NON-NLS-1$
329: script.printAttribute("property", property, true); //$NON-NLS-1$
330: script.printAttribute("file", file, false); //$NON-NLS-1$
331: script.println("/>"); //$NON-NLS-1$
332: }
333: }
|