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