KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > update > core > FeatureContentProvider


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.update.core;
12
13 import java.io.BufferedOutputStream JavaDoc;
14 import java.io.File JavaDoc;
15 import java.io.FileNotFoundException JavaDoc;
16 import java.io.FileOutputStream JavaDoc;
17 import java.io.IOException JavaDoc;
18 import java.io.InputStream JavaDoc;
19 import java.io.OutputStream JavaDoc;
20 import java.net.URL JavaDoc;
21 import java.util.Date JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.Properties JavaDoc;
26 import java.util.Set JavaDoc;
27 import java.util.StringTokenizer JavaDoc;
28
29 import org.eclipse.core.runtime.CoreException;
30 import org.eclipse.core.runtime.IPath;
31 import org.eclipse.core.runtime.Path;
32 import org.eclipse.osgi.util.NLS;
33 import org.eclipse.update.core.model.ContentEntryModel;
34 import org.eclipse.update.core.model.InstallAbortedException;
35 import org.eclipse.update.core.model.NonPluginEntryModel;
36 import org.eclipse.update.core.model.PluginEntryModel;
37 import org.eclipse.update.internal.core.FatalIOException;
38 import org.eclipse.update.internal.core.FeatureDownloadException;
39 import org.eclipse.update.internal.core.FileFragment;
40 import org.eclipse.update.internal.core.InternalSiteManager;
41 import org.eclipse.update.internal.core.LockManager;
42 import org.eclipse.update.internal.core.Messages;
43 import org.eclipse.update.internal.core.UpdateCore;
44 import org.eclipse.update.internal.core.UpdateManagerUtils;
45
46 /**
47  * Base implementation of a feature content provider. This class provides a set
48  * of helper methods useful for implementing feature content providers. In
49  * particular, methods dealing with downloading and caching of feature files.
50  * <p>
51  * This class must be subclassed by clients.
52  * </p>
53  * <p>
54  * <b>Note:</b> This class/interface is part of an interim API that is still under development and expected to
55  * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
56  * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
57  * (repeatedly) as the API evolves.
58  * </p>
59  * @see org.eclipse.update.core.IFeatureContentProvider
60  * @since 2.0
61  */

62 public abstract class FeatureContentProvider
63     implements IFeatureContentProvider {
64
65     private static final boolean SWITCH_COPY_LOCAL = true;
66     //public static long timer = 0;
67

68     //public static long first = 0;
69

70     /**
71      *
72      */

73     public class FileFilter {
74
75         private IPath filterPath = null;
76
77         /**
78          * Constructor for FileFilter.
79          */

80         public FileFilter(String JavaDoc filter) {
81             super();
82             this.filterPath = new Path(filter);
83         }
84
85         /**
86          * returns true if the name matches the rule
87          */

88         public boolean accept(String JavaDoc name) {
89
90             if (name == null)
91                 return false;
92
93             // no '*' pattern matching
94
// must be equals
95
IPath namePath = new Path(name);
96             if (filterPath.lastSegment().indexOf('*') == -1) {
97                 return filterPath.equals(namePath);
98             }
99
100             // check same file extension if extension exists (a.txt/*.txt)
101
// or same file name (a.txt,a.*)
102
String JavaDoc extension = filterPath.getFileExtension();
103             if (extension != null && !extension.equals("*")) { //$NON-NLS-1$
104
if (!extension.equalsIgnoreCase(namePath.getFileExtension()))
105                     return false;
106             } else {
107                 IPath noExtension = filterPath.removeFileExtension();
108                 String JavaDoc fileName = noExtension.lastSegment();
109                 if (!fileName.equals("*")) { //$NON-NLS-1$
110
if (!namePath.lastSegment().startsWith(fileName))
111                         return false;
112                 }
113             }
114
115             // check same path
116
IPath p1 = namePath.removeLastSegments(1);
117             IPath p2 = filterPath.removeLastSegments(1);
118             return p1.equals(p2);
119         }
120
121     }
122
123     private URL JavaDoc base;
124     private IFeature feature;
125     private File JavaDoc tmpDir; // local work area for each provider
126
public static final String JavaDoc JAR_EXTENSION = ".jar"; //$NON-NLS-1$
127

128     private static final String JavaDoc DOT_PERMISSIONS = "permissions.properties"; //$NON-NLS-1$
129
private static final String JavaDoc EXECUTABLES = "permissions.executable"; //$NON-NLS-1$
130

131     /**
132      * Feature content provider constructor
133      *
134      * @param base
135      * feature URL. The interpretation of this URL is specific to
136      * each content provider.
137      * @since 2.0
138      */

139     public FeatureContentProvider(URL JavaDoc base) {
140         this.base = base;
141         this.feature = null;
142     }
143
144     /**
145      * Returns the feature url.
146      *
147      * @see IFeatureContentProvider#getURL()
148      */

149     public URL JavaDoc getURL() {
150         return base;
151     }
152
153     /**
154      * Returns the feature associated with this content provider.
155      *
156      * @see IFeatureContentProvider#getFeature()
157      */

158     public IFeature getFeature() {
159         return feature;
160     }
161
162     /**
163      * Sets the feature associated with this content provider.
164      *
165      * @see IFeatureContentProvider#setFeature(IFeature)
166      */

167     public void setFeature(IFeature feature) {
168         this.feature = feature;
169     }
170
171     /**
172      * Returns the specified reference as a local file system reference. If
173      * required, the file represented by the specified content reference is
174      * first downloaded to the local system
175      *
176      * @param ref
177      * content reference
178      * @param monitor
179      * progress monitor, can be <code>null</code>
180      * @exception IOException
181      * @exception CoreException
182      * @since 2.0
183      */

184     public ContentReference asLocalReference(ContentReference ref, InstallMonitor monitor) throws IOException JavaDoc, CoreException {
185
186         // check to see if this is already a local reference
187
if (ref.isLocalReference())
188             return ref;
189
190         // check to see if we already have a local file for this reference
191
String JavaDoc key = ref.toString();
192
193         // need to synch as another thread my have created the file but
194
// is still copying into it
195
File JavaDoc localFile = null;
196         FileFragment localFileFragment = null;
197         Object JavaDoc keyLock = LockManager.getLock(key);
198         synchronized (keyLock) {
199             localFile = Utilities.lookupLocalFile(key);
200             if (localFile != null) {
201                 // check if the cached file is still valid (no newer version on
202
// server)
203
try {
204                 if (UpdateManagerUtils.isSameTimestamp(ref.asURL(), localFile.lastModified()))
205                     return ref.createContentReference(ref.getIdentifier(), localFile);
206                 } catch(FatalIOException e) {
207                     throw e;
208                 } catch(IOException JavaDoc e) {
209                     throw new FeatureDownloadException(NLS.bind(Messages.FeatureContentProvider_ExceptionDownloading, (new Object JavaDoc[] {getURL().toExternalForm()})), e);
210                 }
211             }
212
213             if (localFile == null) {
214                 localFileFragment = UpdateManagerUtils.lookupLocalFileFragment(key);
215             }
216             //
217
// download the referenced file into local temporary area
218
InputStream JavaDoc is = null;
219             OutputStream JavaDoc os = null;
220             long bytesCopied = 0;
221             long inputLength = 0;
222             boolean success = false;
223             if (monitor != null) {
224                 monitor.saveState();
225                 monitor.setTaskName(Messages.FeatureContentProvider_Downloading);
226                 monitor.subTask(ref.getIdentifier() + " "); //$NON-NLS-1$
227
try {
228                     monitor.setTotalCount(ref.getInputSize());
229                 } catch (FatalIOException e) {
230                     throw e;
231                 } catch (IOException JavaDoc e) {
232                     throw new FeatureDownloadException(NLS.bind(Messages.FeatureContentProvider_ExceptionDownloading, (new Object JavaDoc[] {getURL().toExternalForm()})), e);
233                 }
234                 monitor.showCopyDetails(true);
235             }
236
237             try {
238                 //long startTime = System.nanoTime();
239
if (localFileFragment != null && "http".equals(ref.asURL().getProtocol())) { //$NON-NLS-1$
240
localFile = localFileFragment.getFile();
241                     try {
242                         // get partial input stream
243
is = ref.getPartialInputStream(localFileFragment.getSize());
244                         inputLength = ref.getInputSize() - localFileFragment.getSize();
245                         // get output stream to append to file fragment
246
os = new BufferedOutputStream JavaDoc(
247                         // PAL foundation
248
//new FileOutputStream(localFile, true));
249
new FileOutputStream JavaDoc(localFile.getPath(), true));
250                     } catch (FatalIOException e) {
251                         throw e;
252                     } catch (IOException JavaDoc e) {
253                         try {
254                             if (is != null)
255                                 is.close();
256                         } catch (IOException JavaDoc ioe) {
257                         }
258                         is = null;
259                         os = null;
260                         localFileFragment = null;
261                         throw new FeatureDownloadException(NLS.bind(Messages.FeatureContentProvider_ExceptionDownloading, (new Object JavaDoc[] {getURL().toExternalForm()})), e);
262                     }
263                 }
264                 if (is == null) {
265                     // must download from scratch
266
localFile = Utilities.createLocalFile(getWorkingDirectory(), null);
267                     try {
268                         is = ref.getInputStream();
269                         inputLength = ref.getInputSize();
270                     } catch (FatalIOException e) {
271                         throw Utilities.newCoreException(NLS.bind(Messages.FeatureContentProvider_UnableToRetrieve, (new Object JavaDoc[] {ref})), e);
272                     } catch (IOException JavaDoc e) {
273                         throw new FeatureDownloadException(NLS.bind(Messages.FeatureContentProvider_ExceptionDownloading, (new Object JavaDoc[] {getURL().toExternalForm()})), e);
274                     }
275
276                     try {
277                         os = new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(localFile));
278                     } catch (FileNotFoundException JavaDoc e) {
279                         throw Utilities.newCoreException(NLS.bind(Messages.FeatureContentProvider_UnableToCreate, (new Object JavaDoc[] {localFile})), e);
280                     }
281                 }
282
283                 Date JavaDoc start = new Date JavaDoc();
284                 if (localFileFragment != null) {
285                     bytesCopied = localFileFragment.getSize();
286                     if (monitor != null) {
287                         monitor.setCopyCount(bytesCopied);
288                     }
289                 }
290
291                 // Transfer as many bytes as possible from input to output stream
292
long offset = UpdateManagerUtils.copy(is, os, monitor, inputLength);
293                 if (offset != -1) {
294                     bytesCopied += offset;
295                     if (bytesCopied > 0) {
296                         // preserve partially downloaded file
297
UpdateManagerUtils.mapLocalFileFragment(key, new FileFragment(localFile, bytesCopied));
298                     }
299                     if (monitor.isCanceled()) {
300                         String JavaDoc msg = Messages.Feature_InstallationCancelled;
301                         throw new InstallAbortedException(msg, null);
302                     } else {
303                         throw new FeatureDownloadException(NLS.bind(Messages.FeatureContentProvider_ExceptionDownloading, (new Object JavaDoc[] {getURL().toExternalForm()})), new IOException JavaDoc());
304                     }
305                 } else {
306                     UpdateManagerUtils.unMapLocalFileFragment(key);
307                 }
308
309                 Date JavaDoc stop = new Date JavaDoc();
310                 long timeInseconds = (stop.getTime() - start.getTime()) / 1000;
311                 // time in milliseconds /1000 = time in seconds
312
InternalSiteManager.downloaded(
313                     ref.getInputSize(),
314                     (timeInseconds),
315                     ref.asURL());
316
317                 success = true;
318                 //long endTime = System.nanoTime();
319
// file is downloaded succesfully, map it
320
Utilities.mapLocalFile(key, localFile);
321                 
322                 /*if (ref.asURL().toExternalForm().endsWith("jar")) {
323                     synchronized(this.getClass()) {
324                         timer += (endTime - startTime);
325                         if (first == 0) {
326                             first = endTime - startTime;
327                         }
328                     }
329                 }*/

330             } catch (ClassCastException JavaDoc e) {
331                 throw Utilities.newCoreException(
332                     NLS.bind(Messages.FeatureContentProvider_UnableToCreate, (new Object JavaDoc[] { localFile })),
333                     e);
334             } finally {
335                 //Do not close IS if user cancel,
336
//closing IS will read the entire Stream until the end
337
if (success && is != null)
338                     try {
339                         is.close();
340                     } catch (IOException JavaDoc e) {
341                     }
342                 if (os != null)
343                     try {
344                         os.close(); // should flush buffer stream
345
} catch (IOException JavaDoc e) {
346                     }
347
348                 if (success || bytesCopied > 0) {
349                     // set the timestamp on the temp file to match the remote
350
// timestamp
351
localFile.setLastModified(ref.getLastModified());
352                 }
353                 if (monitor != null)
354                     monitor.restoreState();
355             }
356             LockManager.returnLock(key);
357         } // end lock
358
ContentReference reference =
359             ref.createContentReference(ref.getIdentifier(), localFile);
360         
361         UpdateCore.getPlugin().getUpdateSession().markVisited(ref.asURL());
362         
363         return reference;
364     }
365
366     /**
367      * Returns the specified reference as a local file. If required, the file
368      * represented by the specified content reference is first downloaded to
369      * the local system
370      *
371      * @param ref
372      * content reference
373      * @param monitor
374      * progress monitor, can be <code>null</code>
375      * @exception IOException
376      * @exception CoreException
377      * @since 2.0
378      */

379     public File JavaDoc asLocalFile(ContentReference ref, InstallMonitor monitor) throws IOException JavaDoc, CoreException {
380         File JavaDoc file = ref.asFile();
381         if (file != null && !SWITCH_COPY_LOCAL)
382             return file;
383         ContentReference localRef = asLocalReference(ref, monitor);
384         file = localRef.asFile();
385         return file;
386     }
387
388     /**
389      * Returns working directory for this content provider
390      *
391      * @return working directory
392      * @exception IOException
393      * @since 2.0
394      */

395     protected File JavaDoc getWorkingDirectory() throws IOException JavaDoc {
396         if (tmpDir == null)
397             tmpDir = Utilities.createWorkingDirectory();
398         return tmpDir;
399     }
400
401     /**
402      * Returns the total size of all archives required for the specified
403      * plug-in and non-plug-in entries (the "packaging" view).
404      *
405      * @see IFeatureContentProvider#getDownloadSizeFor(IPluginEntry[],
406      * INonPluginEntry[])
407      */

408     public long getDownloadSizeFor(IPluginEntry[] pluginEntries, INonPluginEntry[] nonPluginEntries) {
409         long result = 0;
410
411         // if both are null or empty, return UNKNOWN size
412
if ((pluginEntries == null || pluginEntries.length == 0) && (nonPluginEntries == null || nonPluginEntries.length == 0)) {
413             return ContentEntryModel.UNKNOWN_SIZE;
414         }
415
416         // loop on plugin entries
417
long size = 0;
418         if (pluginEntries != null)
419             for (int i = 0; i < pluginEntries.length; i++) {
420                 size = ((PluginEntryModel) pluginEntries[i]).getDownloadSize();
421                 if (size == ContentEntryModel.UNKNOWN_SIZE) {
422                     return ContentEntryModel.UNKNOWN_SIZE;
423                 }
424                 result += size;
425             }
426
427         // loop on non plugin entries
428
if (nonPluginEntries != null)
429             for (int i = 0; i < nonPluginEntries.length; i++) {
430                 size = ((NonPluginEntryModel) nonPluginEntries[i]).getDownloadSize();
431                 if (size == ContentEntryModel.UNKNOWN_SIZE) {
432                     return ContentEntryModel.UNKNOWN_SIZE;
433                 }
434                 result += size;
435             }
436
437         return result;
438     }
439
440     /**
441      * Returns the total size of all files required for the specified plug-in
442      * and non-plug-in entries (the "logical" view).
443      *
444      * @see IFeatureContentProvider#getInstallSizeFor(IPluginEntry[],
445      * INonPluginEntry[])
446      */

447     public long getInstallSizeFor(IPluginEntry[] pluginEntries, INonPluginEntry[] nonPluginEntries) {
448         long result = 0;
449
450         // if both are null or empty, return UNKNOWN size
451
if ((pluginEntries == null || pluginEntries.length == 0) && (nonPluginEntries == null || nonPluginEntries.length == 0)) {
452             return ContentEntryModel.UNKNOWN_SIZE;
453         }
454
455         // loop on plugin entries
456
long size = 0;
457         if (pluginEntries != null)
458             for (int i = 0; i < pluginEntries.length; i++) {
459                 size = ((PluginEntryModel) pluginEntries[i]).getInstallSize();
460                 if (size == ContentEntryModel.UNKNOWN_SIZE) {
461                     return ContentEntryModel.UNKNOWN_SIZE;
462                 }
463                 result += size;
464             }
465
466         // loop on non plugin entries
467
if (nonPluginEntries != null)
468             for (int i = 0; i < nonPluginEntries.length; i++) {
469                 size = ((NonPluginEntryModel) nonPluginEntries[i]).getInstallSize();
470                 if (size == ContentEntryModel.UNKNOWN_SIZE) {
471                     return ContentEntryModel.UNKNOWN_SIZE;
472                 }
473                 result += size;
474             }
475
476         return result;
477     }
478
479     /**
480      * Returns the path identifier for a plugin entry. <code>plugins/&lt;pluginId>_&lt;pluginVersion>.jar</code>
481      *
482      * @return the path identifier
483      */

484     protected String JavaDoc getPathID(IPluginEntry entry) {
485         return Site.DEFAULT_PLUGIN_PATH + entry.getVersionedIdentifier().toString() + JAR_EXTENSION;
486     }
487
488     /**
489      * Returns the path identifer for a non plugin entry. <code>features/&lt;featureId>_&lt;featureVersion>/&lt;dataId></code>
490      *
491      * @return the path identifier
492      */

493     protected String JavaDoc getPathID(INonPluginEntry entry) {
494         String JavaDoc nonPluginBaseID = Site.DEFAULT_FEATURE_PATH + feature.getVersionedIdentifier().toString() + "/"; //$NON-NLS-1$
495
return nonPluginBaseID + entry.getIdentifier();
496     }
497
498     /**
499      * Sets the permission of all the ContentReferences Check for the
500      * .permissions contentReference and use it to set the permissions of other
501      * ContentReference
502      */

503     protected void validatePermissions(ContentReference[] references) {
504
505         if (references == null || references.length == 0)
506             return;
507
508         Map JavaDoc permissions = getPermissions(references);
509         if (permissions.isEmpty())
510             return;
511
512         for (int i = 0; i < references.length; i++) {
513             ContentReference contentReference = references[i];
514             String JavaDoc id = contentReference.getIdentifier();
515             Object JavaDoc value = null;
516             if ((value = matchesOneRule(id, permissions)) != null) {
517                 Integer JavaDoc permission = (Integer JavaDoc) value;
518                 contentReference.setPermission(permission.intValue());
519             }
520         }
521     }
522
523     /**
524      * Returns the value of the matching rule or <code>null</code> if none
525      * found. A rule is matched if the id is equals to a key, or if the id is
526      * resolved by a key. if the id is <code>/path/file.txt</code> it is
527      * resolved by <code>/path/*</code> or <code>/path/*.txt</code>
528      *
529      * @param id
530      * the identifier
531      * @param permissions
532      * list of rules
533      * @return Object the value of the matcing rule or <code>null</code>
534      */

535     private Object JavaDoc matchesOneRule(String JavaDoc id, Map JavaDoc permissions) {
536
537         Set JavaDoc keySet = permissions.keySet();
538         Iterator JavaDoc iter = keySet.iterator();
539         while (iter.hasNext()) {
540             FileFilter rule = (FileFilter) iter.next();
541             if (rule.accept(id)) {
542                 return permissions.get(rule);
543             }
544         }
545
546         return null;
547     }
548
549     /*
550      * returns the permission MAP
551      */

552     private Map JavaDoc getPermissions(ContentReference[] references) {
553
554         Map JavaDoc result = new HashMap JavaDoc();
555         // search for .permissions
556
boolean notfound = true;
557         ContentReference permissionReference = null;
558         for (int i = 0; i < references.length && notfound; i++) {
559             ContentReference contentReference = references[i];
560             if (DOT_PERMISSIONS.equals(contentReference.getIdentifier())) {
561                 notfound = false;
562                 permissionReference = contentReference;
563             }
564         }
565         if (notfound)
566             return result;
567
568         Properties JavaDoc prop = new Properties JavaDoc();
569         InputStream JavaDoc propertyStream = null;
570         try {
571             try {
572                 propertyStream = permissionReference.getInputStream();
573                 prop.load(propertyStream);
574             } finally {
575                 if (propertyStream != null)
576                     propertyStream.close();
577             }
578         } catch (IOException JavaDoc e) {
579             UpdateCore.warn("", e); //$NON-NLS-1$
580
}
581
582         String JavaDoc executables = prop.getProperty(EXECUTABLES);
583         if (executables == null)
584             return result;
585
586         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(executables, ","); //$NON-NLS-1$
587
Integer JavaDoc defaultExecutablePermission = new Integer JavaDoc(ContentReference.DEFAULT_EXECUTABLE_PERMISSION);
588         while (tokenizer.hasMoreTokens()) {
589             FileFilter filter = new FileFilter(tokenizer.nextToken());
590             result.put(filter, defaultExecutablePermission);
591         }
592
593         return result;
594     }
595 }
596
Popular Tags