001: /*******************************************************************************
002: * Copyright (c) 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 Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.internal.ui.util;
011:
012: import java.io.ByteArrayInputStream;
013: import java.io.File;
014: import java.io.FileInputStream;
015: import java.io.IOException;
016: import java.io.InputStream;
017: import java.io.InputStreamReader;
018: import java.net.MalformedURLException;
019: import java.net.URL;
020: import java.util.ArrayList;
021: import java.util.Enumeration;
022: import java.util.HashMap;
023: import java.util.Iterator;
024: import java.util.Map;
025: import java.util.zip.ZipEntry;
026: import java.util.zip.ZipException;
027: import java.util.zip.ZipFile;
028:
029: import org.eclipse.core.resources.IContainer;
030: import org.eclipse.core.resources.IFile;
031: import org.eclipse.core.resources.IFolder;
032: import org.eclipse.core.resources.IProject;
033: import org.eclipse.core.runtime.CoreException;
034: import org.eclipse.core.runtime.FileLocator;
035: import org.eclipse.core.runtime.IPath;
036: import org.eclipse.core.runtime.IProgressMonitor;
037: import org.eclipse.core.runtime.Path;
038: import org.eclipse.core.runtime.Platform;
039: import org.eclipse.jdt.core.IClasspathEntry;
040: import org.eclipse.jdt.core.IJavaProject;
041: import org.eclipse.jdt.core.JavaCore;
042: import org.eclipse.jdt.core.JavaModelException;
043: import org.eclipse.pde.core.plugin.IPlugin;
044: import org.eclipse.pde.core.plugin.IPluginBase;
045: import org.eclipse.pde.core.plugin.IPluginModel;
046: import org.eclipse.pde.core.plugin.IPluginModelBase;
047: import org.eclipse.pde.internal.core.TargetPlatformHelper;
048: import org.eclipse.pde.internal.core.ibundle.IBundlePluginBase;
049: import org.eclipse.pde.internal.ui.PDEUIMessages;
050: import org.eclipse.pde.internal.ui.wizards.product.ISplashHandlerConstants;
051: import org.eclipse.pde.internal.ui.wizards.product.UpdateSplashHandlerAction;
052: import org.eclipse.pde.internal.ui.wizards.templates.ControlStack;
053: import org.eclipse.pde.ui.templates.IVariableProvider;
054: import org.osgi.framework.Bundle;
055:
056: /**
057: * TemplateFileGenerator
058: *
059: */
060: public class TemplateFileGenerator implements IVariableProvider {
061:
062: // TODO: MP: SPLASH: Merge this utility back with template (maybe as an abstract base class?) - Extracted from org.eclipse.pde.ui.templates.AbstractTemplateSection
063: // TODO: MP: SPLASH: Major code-clean-up required
064:
065: /**
066: * The key for the main plug-in class of the plug-in that the template is
067: * used for (value="pluginClass"). The return value is a fully-qualified class name.
068: */
069: public static final String KEY_PLUGIN_CLASS = "pluginClass"; //$NON-NLS-1$
070:
071: /**
072: * The key for the simple class name of a bundle activator (value="activator")
073: *
074: * @since 3.3
075: */
076: public static final String KEY_ACTIVATOR_SIMPLE = "activator"; //$NON-NLS-1$
077: /**
078: * The key for the plug-in id of the plug-in that the template is used for
079: * (value="pluginId").
080: */
081: public static final String KEY_PLUGIN_ID = "pluginId"; //$NON-NLS-1$
082: /**
083: * The key for the plug-in name of the plug-in that the template is used for
084: * (value="pluginName").
085: */
086: public static final String KEY_PLUGIN_NAME = "pluginName"; //$NON-NLS-1$
087: /**
088: * The key for the package name that will be created by this teamplate
089: * (value="packageName").
090: */
091: public static final String KEY_PACKAGE_NAME = "packageName"; //$NON-NLS-1$
092:
093: private IProject fProject;
094:
095: private IPluginModelBase fModel;
096:
097: private String fPluginID;
098:
099: private String fPackage;
100:
101: private String fClass;
102:
103: private String fTemplate;
104:
105: /**
106: * @param project
107: * @param model
108: */
109: public TemplateFileGenerator(IProject project,
110: IPluginModelBase model, String pluginID,
111: String targetPackage, String targetClass, String template) {
112: fProject = project;
113: fModel = model;
114: fPluginID = pluginID;
115: fPackage = targetPackage;
116: fClass = targetClass;
117: fTemplate = template;
118: }
119:
120: /**
121: * Generates files as part of the template execution. The default
122: * implementation uses template location as a root of the file templates.
123: * {@link #generateFiles(IProgressMonitor monitor, URL locationUrl)} on how
124: * the location gets processed.
125: *
126: * @param monitor
127: * progress monitor to use to indicate generation progress
128: */
129: public void generateFiles(IProgressMonitor monitor)
130: throws CoreException {
131: // Generate files using the default template location
132: generateFiles(monitor, getTemplateLocation());
133: // Generate files using the shared branding location (for splash screen)
134: Bundle templateBundle = Platform
135: .getBundle("org.eclipse.pde.ui.templates"); //$NON-NLS-1$
136: if (templateBundle == null) {
137: return;
138: }
139: generateFiles(monitor, templateBundle.getEntry("branding/")); //$NON-NLS-1$
140: }
141:
142: public URL getTemplateLocation() {
143: Bundle bundle = Platform
144: .getBundle("org.eclipse.pde.ui.templates"); //$NON-NLS-1$
145: if (bundle == null) {
146: return null;
147: }
148:
149: try {
150: String[] candidates = getDirectoryCandidates();
151: for (int i = 0; i < candidates.length; i++) {
152: if (bundle.getEntry(candidates[i]) != null) {
153: URL candidate = new URL(
154: bundle.getEntry("/"), candidates[i]); //$NON-NLS-1$
155: return candidate;
156: }
157: }
158: } catch (MalformedURLException e) {
159: }
160: return null;
161: }
162:
163: /**
164: * Generates files as part of the template execution.
165: * The files found in the location are processed in the following way:
166: * <ul>
167: * <li>Files and folders found in the directory <samp>bin </samp> are
168: * copied into the target project without modification.</li>
169: * <li>Files found in the directory <samp>java </samp> are copied into the
170: * Java source folder by creating the folder structure that corresponds to
171: * the package name (variable <samp>packageName </samp>). Java files are
172: * subject to conditional generation and variable replacement.</li>
173: * <li>All other files and folders are copied directly into the target
174: * folder with the conditional generation and variable replacement for
175: * files. Variable replacement also includes file names.</li>
176: * </ul>
177: *
178: * @since 3.3
179: * @param monitor
180: * progress monitor to use to indicate generation progress
181: * @param locationUrl a url pointing to a file/directory that will be copied into the template
182: */
183: protected void generateFiles(IProgressMonitor monitor,
184: URL locationUrl) throws CoreException {
185: monitor
186: .setTaskName(PDEUIMessages.AbstractTemplateSection_generating);
187:
188: if (locationUrl == null) {
189: return;
190: }
191: try {
192: locationUrl = FileLocator.resolve(locationUrl);
193: locationUrl = FileLocator.toFileURL(locationUrl);
194: } catch (IOException e) {
195: return;
196: }
197: if ("file".equals(locationUrl.getProtocol())) { //$NON-NLS-1$
198: File templateDirectory = new File(locationUrl.getFile());
199: if (!templateDirectory.exists())
200: return;
201: generateFiles(templateDirectory, fProject, true, false,
202: monitor);
203: } else if ("jar".equals(locationUrl.getProtocol())) { //$NON-NLS-1$
204: String file = locationUrl.getFile();
205: int exclamation = file.indexOf('!');
206: if (exclamation < 0)
207: return;
208: URL fileUrl = null;
209: try {
210: fileUrl = new URL(file.substring(0, exclamation));
211: } catch (MalformedURLException mue) {
212: return;
213: }
214: File pluginJar = new File(fileUrl.getFile());
215: if (!pluginJar.exists())
216: return;
217: String templateDirectory = file.substring(exclamation + 1); // "/some/path/"
218: IPath path = new Path(templateDirectory);
219: ZipFile zipFile = null;
220: try {
221: zipFile = new ZipFile(pluginJar);
222: generateFiles(zipFile, path, fProject, true, false,
223: monitor);
224: } catch (ZipException ze) {
225: } catch (IOException ioe) {
226: } finally {
227: if (zipFile != null) {
228: try {
229: zipFile.close();
230: } catch (IOException e) {
231: }
232: }
233: }
234:
235: }
236: monitor.subTask(""); //$NON-NLS-1$
237: monitor.worked(1);
238: }
239:
240: private void generateFiles(File src, IContainer dst,
241: boolean firstLevel, boolean binary, IProgressMonitor monitor)
242: throws CoreException {
243: File[] members = src.listFiles();
244:
245: for (int i = 0; i < members.length; i++) {
246: File member = members[i];
247: if (member.isDirectory()) {
248: IContainer dstContainer = null;
249:
250: if (firstLevel) {
251: binary = false;
252: if (!isOkToCreateFolder(member))
253: continue;
254:
255: if (member.getName().equals("java")) { //$NON-NLS-1$
256: IFolder sourceFolder = getSourceFolder(monitor);
257: dstContainer = generateJavaSourceFolder(
258: sourceFolder, monitor);
259: } else if (member.getName().equals("bin")) { //$NON-NLS-1$
260: binary = true;
261: dstContainer = dst;
262: }
263: }
264: if (dstContainer == null) {
265: if (isOkToCreateFolder(member) == false)
266: continue;
267: String folderName = getProcessedString(member
268: .getName(), member.getName());
269: dstContainer = dst.getFolder(new Path(folderName));
270: }
271: if (dstContainer instanceof IFolder
272: && !dstContainer.exists())
273: ((IFolder) dstContainer)
274: .create(true, true, monitor);
275: generateFiles(member, dstContainer, false, binary,
276: monitor);
277: } else {
278: if (isOkToCreateFile(member)) {
279: if (firstLevel)
280: binary = false;
281: InputStream in = null;
282: try {
283: in = new FileInputStream(member);
284: copyFile(member.getName(), in, dst, binary,
285: monitor);
286: } catch (IOException ioe) {
287: } finally {
288: if (in != null)
289: try {
290: in.close();
291: } catch (IOException ioe2) {
292: }
293: }
294: }
295: }
296: }
297: }
298:
299: private void copyFile(String fileName, InputStream input,
300: IContainer dst, boolean binary, IProgressMonitor monitor)
301: throws CoreException {
302: String targetFileName = getProcessedString(fileName, fileName);
303:
304: monitor.subTask(targetFileName);
305: IFile dstFile = dst.getFile(new Path(targetFileName));
306:
307: try {
308: InputStream stream = getProcessedStream(fileName, input,
309: binary);
310: if (dstFile.exists()) {
311: dstFile.setContents(stream, true, true, monitor);
312: } else {
313: dstFile.create(stream, true, monitor);
314: }
315: stream.close();
316:
317: } catch (IOException e) {
318: }
319: }
320:
321: private void generateFiles(ZipFile zipFile, IPath path,
322: IContainer dst, boolean firstLevel, boolean binary,
323: IProgressMonitor monitor) throws CoreException {
324: int pathLength = path.segmentCount();
325: // Immidiate children
326: Map childZipEntries = new HashMap(); // "dir/" or "dir/file.java"
327:
328: for (Enumeration zipEntries = zipFile.entries(); zipEntries
329: .hasMoreElements();) {
330: ZipEntry zipEntry = (ZipEntry) zipEntries.nextElement();
331: IPath entryPath = new Path(zipEntry.getName());
332: if (entryPath.segmentCount() <= pathLength) {
333: // ancestor or current directory
334: continue;
335: }
336: if (!path.isPrefixOf(entryPath)) {
337: // not a descendant
338: continue;
339: }
340: if (entryPath.segmentCount() == pathLength + 1) {
341: childZipEntries.put(zipEntry.getName(), zipEntry);
342: } else {
343: String name = entryPath.uptoSegment(pathLength + 1)
344: .addTrailingSeparator().toString();
345: if (!childZipEntries.containsKey(name)) {
346: ZipEntry dirEntry = new ZipEntry(name);
347: childZipEntries.put(name, dirEntry);
348: }
349: }
350: }
351:
352: for (Iterator it = childZipEntries.values().iterator(); it
353: .hasNext();) {
354: ZipEntry zipEnry = (ZipEntry) it.next();
355: String name = new Path(zipEnry.getName()).lastSegment()
356: .toString();
357: if (zipEnry.isDirectory()) {
358: IContainer dstContainer = null;
359:
360: if (firstLevel) {
361: binary = false;
362: if (name.equals("java")) { //$NON-NLS-1$
363: IFolder sourceFolder = getSourceFolder(monitor);
364: dstContainer = generateJavaSourceFolder(
365: sourceFolder, monitor);
366: } else if (name.equals("bin")) { //$NON-NLS-1$
367: binary = true;
368: dstContainer = dst;
369: }
370: }
371: if (dstContainer == null) {
372: if (isOkToCreateFolder(new File(path.toFile(), name)) == false)
373: continue;
374: String folderName = getProcessedString(name, name);
375: dstContainer = dst.getFolder(new Path(folderName));
376: }
377: if (dstContainer instanceof IFolder
378: && !dstContainer.exists())
379: ((IFolder) dstContainer)
380: .create(true, true, monitor);
381: generateFiles(zipFile, path.append(name), dstContainer,
382: false, binary, monitor);
383: } else {
384: if (isOkToCreateFile(new File(path.toFile(), name))) {
385: if (firstLevel)
386: binary = false;
387: InputStream in = null;
388: try {
389: in = zipFile.getInputStream(zipEnry);
390: copyFile(name, in, dst, binary, monitor);
391: } catch (IOException ioe) {
392: } finally {
393: if (in != null)
394: try {
395: in.close();
396: } catch (IOException ioe2) {
397: }
398: }
399: }
400: }
401: }
402: }
403:
404: /**
405: * Tests if the folder found in the template location should be created in
406: * the target project. Subclasses may use this method to conditionally block
407: * the creation of entire directories (subject to user choices).
408: *
409: * @param sourceFolder
410: * the folder that is tested
411: * @return <code>true</code> if the provided folder should be created in
412: * the workspace, <code>false</code> if the values of the
413: * substitution variables indicate otherwise.
414: */
415: protected boolean isOkToCreateFolder(File sourceFolder) {
416: boolean extensibleTemplateSelected = UpdateSplashHandlerAction
417: .isExtensibleTemplateSelected(fTemplate);
418: String sourceFolderString = sourceFolder.toString();
419:
420: if ((extensibleTemplateSelected == false)
421: && sourceFolderString.endsWith("icons")) { //$NON-NLS-1$
422: return false;
423: } else if ((extensibleTemplateSelected == false)
424: && sourceFolderString.endsWith("schema")) { //$NON-NLS-1$
425: return false;
426: }
427:
428: return true;
429: }
430:
431: /**
432: * Tests if the file found in the template location should be created in the
433: * target project. Subclasses may use this method to conditionally block
434: * creation of the file (subject to user choices).
435: *
436: * @param sourceFile
437: * the file found in the template location that needs to be
438: * created.
439: * @return <samp>true </samp> if the specified file should be created in the
440: * project or <samp>false </samp> to skip it. The default
441: * implementation is <samp>true </samp>.
442: */
443: protected boolean isOkToCreateFile(File sourceFile) {
444: String javaSuffix = ".java"; //$NON-NLS-1$
445: String targetFile = fClass + javaSuffix;
446: String copyFile = sourceFile.toString();
447: // Prevent needless copying
448: // TODO: MP: SPLASH: Propagate / share copy prevention code with org.eclipse.pde.internal.ui.templates.ide.SplashHandlersTemplate
449: if (copyFile.endsWith(javaSuffix)) {
450: if ((copyFile.endsWith(targetFile) == false)
451: || fProject
452: .exists(new Path(
453: "src" + '/' + fPackage.replace('.', '/') + '/' + targetFile))) { //$NON-NLS-1$
454: return false;
455: }
456: } else if (copyFile.endsWith("splash.bmp") && //$NON-NLS-1$
457: (fProject.exists(new Path("splash.bmp")))) { //$NON-NLS-1$
458: return false;
459: } else if (copyFile.endsWith(".png")) { //$NON-NLS-1$
460: if (copyFile.endsWith("af.png") && //$NON-NLS-1$
461: fProject.exists(new Path("icons/af.png"))) { //$NON-NLS-1$
462: return false;
463: } else if (copyFile.endsWith("embedded.png") && //$NON-NLS-1$
464: fProject.exists(new Path("icons/embedded.png"))) { //$NON-NLS-1$
465: return false;
466: } else if (copyFile.endsWith("enterprise.png") && //$NON-NLS-1$
467: fProject.exists(new Path("icons/enterprise.png"))) { //$NON-NLS-1$
468: return false;
469: } else if (copyFile.endsWith("rcp.png") && //$NON-NLS-1$
470: fProject.exists(new Path("icons/rcp.png"))) { //$NON-NLS-1$
471: return false;
472: } else if (copyFile.endsWith("languages.png") && //$NON-NLS-1$
473: fProject.exists(new Path("icons/languages.png"))) { //$NON-NLS-1$
474: return false;
475: }
476: } else if (copyFile.endsWith("splashExtension.exsd") && //$NON-NLS-1$
477: (fProject
478: .exists(new Path("schema/splashExtension.exsd")))) { //$NON-NLS-1$
479: return false;
480: }
481:
482: return true;
483: }
484:
485: /**
486: * Returns the folder with Java files in the target project. The default
487: * implementation looks for source folders in the classpath of the target
488: * folders and picks the first one encountered. Subclasses may override this
489: * behaviour.
490: *
491: * @param monitor
492: * progress monitor to use
493: * @return source folder that will be used to generate Java files or
494: * <samp>null </samp> if none found.
495: */
496:
497: protected IFolder getSourceFolder(IProgressMonitor monitor)
498: throws CoreException {
499: IFolder sourceFolder = null;
500:
501: try {
502: IJavaProject javaProject = JavaCore.create(fProject);
503: IClasspathEntry[] classpath = javaProject.getRawClasspath();
504: for (int i = 0; i < classpath.length; i++) {
505: IClasspathEntry entry = classpath[i];
506: if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
507: IPath path = entry.getPath().removeFirstSegments(1);
508: if (path.segmentCount() > 0)
509: sourceFolder = fProject.getFolder(path);
510: break;
511: }
512: }
513: } catch (JavaModelException e) {
514: }
515: return sourceFolder;
516: }
517:
518: /**
519: * @see IVariableProvider#getValue(String)
520: */
521:
522: public Object getValue(String key) {
523: return getKeyValue(key);
524: }
525:
526: private IFolder generateJavaSourceFolder(IFolder sourceFolder,
527: IProgressMonitor monitor) throws CoreException {
528: Object packageValue = getValue(KEY_PACKAGE_NAME);
529: //
530: String packageName = packageValue != null ? packageValue
531: .toString() : null;
532: if (packageName == null)
533: packageName = fModel.getPluginBase().getId();
534: IPath path = new Path(packageName.replace('.',
535: File.separatorChar));
536: if (sourceFolder != null)
537: path = sourceFolder.getProjectRelativePath().append(path);
538:
539: for (int i = 1; i <= path.segmentCount(); i++) {
540: IPath subpath = path.uptoSegment(i);
541: IFolder subfolder = fProject.getFolder(subpath);
542: if (subfolder.exists() == false)
543: subfolder.create(true, true, monitor);
544: }
545: return fProject.getFolder(path);
546: }
547:
548: private String getProcessedString(String fileName, String source) {
549: if (source.indexOf('$') == -1)
550: return source;
551: int loc = -1;
552: StringBuffer buffer = new StringBuffer();
553: boolean replacementMode = false;
554: for (int i = 0; i < source.length(); i++) {
555: char c = source.charAt(i);
556: if (c == '$') {
557: if (replacementMode) {
558: String key = source.substring(loc, i);
559: String value = key.length() == 0 ? "$" //$NON-NLS-1$
560: : getReplacementString(fileName, key);
561: buffer.append(value);
562: replacementMode = false;
563: } else {
564: replacementMode = true;
565: loc = i + 1;
566: continue;
567: }
568: } else if (!replacementMode)
569: buffer.append(c);
570: }
571: return buffer.toString();
572: }
573:
574: /**
575: * The default implementation of this method provides values of the
576: * following keys: <samp>pluginClass </samp>, <samp>pluginId </samp> and
577: * <samp>pluginName </samp>.
578: *
579: * @see ITemplateSection#getReplacementString(String,String)
580: */
581: public String getReplacementString(String fileName, String key) {
582: String result = getKeyValue(key);
583: return result != null ? result : key;
584: }
585:
586: private String getKeyValue(String key) {
587: if (fModel == null)
588: return null;
589:
590: // TODO: MP: SPLASH: Broken and not needed, underlying model does not have class, id, translated name parameters defined
591: if (key.equals(KEY_PLUGIN_CLASS)
592: && fModel instanceof IPluginModel) {
593: IPlugin plugin = (IPlugin) fModel.getPluginBase();
594: return plugin.getClassName();
595: }
596:
597: // TODO: MP: SPLASH: Broken and not needed, underlying model does not have class, id, translated name parameters defined
598: if (key.equals(KEY_ACTIVATOR_SIMPLE)
599: && fModel instanceof IPluginModel) {
600: IPlugin plugin = (IPlugin) fModel.getPluginBase();
601: String qualified = plugin.getClassName();
602: if (qualified != null) {
603: int lastDot = qualified.lastIndexOf('.');
604: return (lastDot != -1 && lastDot < qualified.length() - 1) ? qualified
605: .substring(lastDot + 1)
606: : qualified;
607: }
608: }
609:
610: if (key.equals(KEY_PLUGIN_ID)) {
611: return fPluginID;
612: // Old implementation, does not work
613: //IPluginBase plugin = fModel.getPluginBase();
614: //return plugin.getId();
615: }
616: // TODO: MP: SPLASH: Broken and not needed, underlying model does not have class, id, translated name parameters defined
617: if (key.equals(KEY_PLUGIN_NAME)) {
618: IPluginBase plugin = fModel.getPluginBase();
619: return plugin.getTranslatedName();
620: }
621:
622: if (key.equals(KEY_PACKAGE_NAME)
623: && fModel instanceof IPluginModel) {
624: return fPackage;
625: // Old implementation, does not work
626: // IPlugin plugin = (IPlugin) fModel.getPluginBase();
627: // String qualified = plugin.getClassName();
628: // if (qualified != null) {
629: // int lastDot = qualified.lastIndexOf('.');
630: // return (lastDot != -1) ? qualified.substring(0, lastDot) : qualified;
631: // }
632: }
633: return null;
634: }
635:
636: private InputStream getProcessedStream(String fileName,
637: InputStream stream, boolean binary) throws IOException,
638: CoreException {
639: if (binary)
640: return stream;
641:
642: InputStreamReader reader = new InputStreamReader(stream);
643: int bufsize = 1024;
644: char[] cbuffer = new char[bufsize];
645: int read = 0;
646: StringBuffer keyBuffer = new StringBuffer();
647: StringBuffer outBuffer = new StringBuffer();
648: StringBuffer preBuffer = new StringBuffer();
649: boolean newLine = true;
650: ControlStack preStack = new ControlStack();
651: preStack.setValueProvider(this );
652:
653: boolean replacementMode = false;
654: boolean preprocessorMode = false;
655: boolean escape = false;
656: while (read != -1) {
657: read = reader.read(cbuffer);
658: for (int i = 0; i < read; i++) {
659: char c = cbuffer[i];
660:
661: if (escape) {
662: StringBuffer buf = preprocessorMode ? preBuffer
663: : outBuffer;
664: buf.append(c);
665: escape = false;
666: continue;
667: }
668:
669: if (newLine && c == '%') {
670: // preprocessor line
671: preprocessorMode = true;
672: preBuffer.delete(0, preBuffer.length());
673: continue;
674: }
675: if (preprocessorMode) {
676: if (c == '\\') {
677: escape = true;
678: continue;
679: }
680: if (c == '\n') {
681: // handle line
682: preprocessorMode = false;
683: newLine = true;
684: String line = preBuffer.toString().trim();
685: preStack.processLine(line);
686: continue;
687: }
688: preBuffer.append(c);
689:
690: continue;
691: }
692:
693: if (preStack.getCurrentState() == false) {
694: continue;
695: }
696:
697: if (c == '$') {
698: if (replacementMode) {
699: replacementMode = false;
700: String key = keyBuffer.toString();
701: String value = key.length() == 0 ? "$" //$NON-NLS-1$
702: : getReplacementString(fileName, key);
703: outBuffer.append(value);
704: keyBuffer.delete(0, keyBuffer.length());
705: } else {
706: replacementMode = true;
707: }
708: } else {
709: if (replacementMode)
710: keyBuffer.append(c);
711: else {
712: outBuffer.append(c);
713: if (c == '\n') {
714: newLine = true;
715: } else
716: newLine = false;
717: }
718: }
719: }
720: }
721: return new ByteArrayInputStream(outBuffer.toString().getBytes(
722: fProject.getDefaultCharset()));
723: }
724:
725: private String[] getDirectoryCandidates() {
726: double version = getTargetVersion();
727: ArrayList result = new ArrayList();
728: if (version >= 3.3)
729: result.add("templates_3.3" + "/" + getSectionId() + "/"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
730: if (version >= 3.2)
731: result.add("templates_3.2" + "/" + getSectionId() + "/"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
732: if (version >= 3.1)
733: result.add("templates_3.1" + "/" + getSectionId() + "/"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
734: if (version >= 3.0)
735: result.add("templates_3.0" + "/" + getSectionId() + "/"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
736: return (String[]) result.toArray(new String[result.size()]);
737: }
738:
739: public String getSectionId() {
740: return ISplashHandlerConstants.F_UNQUALIFIED_EXTENSION_ID;
741: }
742:
743: protected double getTargetVersion() {
744: try {
745: IPluginBase plugin = fModel.getPluginBase();
746: if (plugin instanceof IBundlePluginBase)
747: return Double.parseDouble(((IBundlePluginBase) plugin)
748: .getTargetVersion());
749: } catch (NumberFormatException e) {
750: }
751: return TargetPlatformHelper.getTargetVersion();
752: }
753:
754: }
|