[475763] Improve caching resources with no-cache header specified
diff --git a/plugins/org.eclipse.wst.common.uriresolver/META-INF/MANIFEST.MF b/plugins/org.eclipse.wst.common.uriresolver/META-INF/MANIFEST.MF
index ec3b9a7..00eca94 100644
--- a/plugins/org.eclipse.wst.common.uriresolver/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.wst.common.uriresolver/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.wst.common.uriresolver; singleton:=true
-Bundle-Version: 1.2.200.qualifier
+Bundle-Version: 1.2.300.qualifier
 Bundle-Activator: org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
diff --git a/plugins/org.eclipse.wst.common.uriresolver/pom.xml b/plugins/org.eclipse.wst.common.uriresolver/pom.xml
index 46006e5..15d0953 100644
--- a/plugins/org.eclipse.wst.common.uriresolver/pom.xml
+++ b/plugins/org.eclipse.wst.common.uriresolver/pom.xml
@@ -22,6 +22,6 @@
 

   <groupId>org.eclipse.webtools.common</groupId>

   <artifactId>org.eclipse.wst.common.uriresolver</artifactId>

-  <version>1.2.200-SNAPSHOT</version>

+  <version>1.2.300-SNAPSHOT</version>

   <packaging>eclipse-plugin</packaging>

 </project>

diff --git a/plugins/org.eclipse.wst.common.uriresolver/src/org/eclipse/wst/common/uriresolver/internal/ExtensibleURIResolver.java b/plugins/org.eclipse.wst.common.uriresolver/src/org/eclipse/wst/common/uriresolver/internal/ExtensibleURIResolver.java
index e9b2c17..ecad415 100644
--- a/plugins/org.eclipse.wst.common.uriresolver/src/org/eclipse/wst/common/uriresolver/internal/ExtensibleURIResolver.java
+++ b/plugins/org.eclipse.wst.common.uriresolver/src/org/eclipse/wst/common/uriresolver/internal/ExtensibleURIResolver.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,6 +13,7 @@
 
 import java.util.Iterator;
 import java.util.List;
+
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.ResourcesPlugin;
@@ -140,7 +141,7 @@
 	  {
 	    // normalize the URI
 	    URI systemURI = URI.createURI(systemId);
-	    if (systemURI.isRelative())
+	    if (systemURI.isRelative() && baseLocation != null)
 	    {
 	      baseLocation = baseLocation.replace('\\','/');
 	      URI baseURI = URI.createURI(baseLocation);
diff --git a/plugins/org.eclipse.wst.internet.cache/META-INF/MANIFEST.MF b/plugins/org.eclipse.wst.internet.cache/META-INF/MANIFEST.MF
index 3070963..318b278 100644
--- a/plugins/org.eclipse.wst.internet.cache/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.wst.internet.cache/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %_PLUGIN_NAME
 Bundle-SymbolicName: org.eclipse.wst.internet.cache; singleton:=true
-Bundle-Version: 1.0.701.qualifier
+Bundle-Version: 1.0.800.qualifier
 Bundle-Activator: org.eclipse.wst.internet.cache.internal.CachePlugin
 Bundle-Vendor: %_PLUGIN_PROVIDER
 Bundle-Localization: plugin
diff --git a/plugins/org.eclipse.wst.internet.cache/plugin.properties b/plugins/org.eclipse.wst.internet.cache/plugin.properties
index 1353df2..486991e 100644
--- a/plugins/org.eclipse.wst.internet.cache/plugin.properties
+++ b/plugins/org.eclipse.wst.internet.cache/plugin.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2005, 2010 IBM Corporation and others.
+# Copyright (c) 2005, 2017 IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -10,8 +10,7 @@
 ###############################################################################
 
 _PLUGIN_PROVIDER                       = Eclipse Web Tools Platform
-_PLUGIN_NAME                           = Cache URI Resolver Plug-in
+_PLUGIN_NAME                           = Caching URI Resolver
 
 cacheResource                          = Cache Resource
 _UI_CACHE_PREFERENCE_PAGE_TITLE        = Cache
-
diff --git a/plugins/org.eclipse.wst.internet.cache/pom.xml b/plugins/org.eclipse.wst.internet.cache/pom.xml
index 8c40b4a..927e069 100644
--- a/plugins/org.eclipse.wst.internet.cache/pom.xml
+++ b/plugins/org.eclipse.wst.internet.cache/pom.xml
@@ -22,6 +22,6 @@
 

   <groupId>org.eclipse.webtools.common</groupId>

   <artifactId>org.eclipse.wst.internet.cache</artifactId>

-  <version>1.0.701-SNAPSHOT</version>

+  <version>1.0.800-SNAPSHOT</version>

   <packaging>eclipse-plugin</packaging>

 </project>

diff --git a/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/Cache.java b/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/Cache.java
index 8fbb4a3..863f379 100644
--- a/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/Cache.java
+++ b/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/Cache.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2015 IBM Corporation and others.
+ * Copyright (c) 2001, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,6 +11,7 @@
 
 package org.eclipse.wst.internet.cache.internal;
 
+import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
@@ -63,10 +64,7 @@
   private static final String CACHE_EXTENSION = ".cache";
   private static final String CACHE_PREFIX = "wtpcache";
   private static final String CACHE_SUFFIX = null;
-  /**
-   * The default timeout for a cache entry is 1 day.
-   */
-  private static final long TIMEOUT = 86400000;
+
 	
   /**
    * The one and only instance of the cache.
@@ -149,7 +147,12 @@
 	  }
 	  return FILE_PROTOCOL + cacheLocation.toString() + "/" + result.getLocalFile();
   }
-  
+
+  private static long getTimeout()
+  {
+    return CachePlugin.getDefault().getCacheTimeout();
+  }
+
   /**
    * Get the list of uncached resources.
    * 
@@ -206,8 +209,8 @@
 			  conn = url.openConnection();
 		  }
 		  // Determine if this resource can be cached.
-		  if(conn.getUseCaches())
-		  {
+		  if(CachePlugin.getDefault().isIgnoreNoCacheHeader() || conn.getUseCaches())
+          {
 			is = URIHelper.getInputStream(actualUri, 0);
 	    	if (is == null) {
 	    	  uncached.add(uri);
@@ -222,7 +225,7 @@
 			  fileName = rand.nextInt() + CACHE_EXTENSION;
 			  file = new File(cacheLocation,fileName);
 		    }
-		    os = new FileOutputStream(file);
+		    os = new BufferedOutputStream(new FileOutputStream(file));
 		    byte[] bytes = new byte[1024];
 		    int bytelength;
 		    while((bytelength = is.read(bytes)) != -1)
@@ -233,7 +236,7 @@
 		    long expiration = conn.getExpiration();
 			if(expiration == 0)
 			{
-			  expiration = System.currentTimeMillis() + TIMEOUT;
+			  expiration = System.currentTimeMillis() + getTimeout();
 			}
 		    cacheEntry = new CacheEntry(uri, fileName, lastModified, expiration);
 		    cache.put(uri,cacheEntry);
@@ -300,7 +303,7 @@
 			long expiration = conn.getExpiration();
 		    if(expiration == 0)
 			{
-			  expiration = System.currentTimeMillis() + TIMEOUT;
+			  expiration = System.currentTimeMillis() + getTimeout();
 			}
 			
 		    is = conn.getInputStream();
@@ -331,7 +334,7 @@
 			long expiration = conn.getExpiration();
 			if(expiration == 0)
 			{
-			  expiration = System.currentTimeMillis() + TIMEOUT;
+			  expiration = System.currentTimeMillis() + getTimeout();
 			}
 			cacheEntry.setExpiration(expiration);
 		  }
diff --git a/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/CacheMessages.java b/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/CacheMessages.java
index f8fee2f..d4ad4ea 100644
--- a/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/CacheMessages.java
+++ b/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/CacheMessages.java
@@ -26,6 +26,8 @@
 	public static String _UI_BUTTON_DELETE_ENTRY;
 	public static String _UI_PREF_CACHE_ENTRIES_TITLE;
 	public static String _UI_PREF_CACHE_CACHE_OPTION;
+	public static String _UI_PREF_CACHE_IGNORE_NO_CACHE_HEADER;
+	public static String _UI_PREF_CACHE_CACHE_DURATION_LABEL;
 	public static String _UI_PREF_CACHE_ABOUT;
 	public static String _UI_PREF_PROMPT_FOR_DISAGREED_LICENSES;
 	public static String _UI_CACHE_MONITOR_NAME;
diff --git a/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/CachePlugin.java b/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/CachePlugin.java
index 4bff91b..7bf01fc 100644
--- a/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/CachePlugin.java
+++ b/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/CachePlugin.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2012 IBM Corporation and others.
+ * Copyright (c) 2001, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -139,6 +139,58 @@
 	return true;
   }
   
+  
+  /**
+   * Set whether or not the cache job should ignore a no-cache header
+   * 
+   * @param enabled If true the cache will ignore no-cache header, false to respect no-cache header
+   */
+  public void setIgnoreNoCacheHeader(boolean ignore) 
+  {
+	getPluginPreferences().setValue(PreferenceConstants.IGNORE_NO_CACHE_HEADER, ignore);
+  }
+
+  /**
+   * Returns true if the cache is ignoring no-cache header, false otherwise.
+   * 
+   * @return True if the cache is ignoring no-cache header, false otherwise.
+   */
+  public boolean isIgnoreNoCacheHeader() 
+  {
+	if (getPluginPreferences().contains(PreferenceConstants.IGNORE_NO_CACHE_HEADER))
+	  return getPluginPreferences().getBoolean(PreferenceConstants.IGNORE_NO_CACHE_HEADER);
+	return false;
+  }
+
+  
+  
+  /**
+   * Set the timeout for caching
+   * 
+   * @param timeout a timeout in ms
+   */
+  public void setCacheTimeout(long timeout) 
+  {
+	getPluginPreferences().setValue(PreferenceConstants.CACHE_DURATION, timeout);
+  }
+
+  /**
+   * Returns the number of ms to cache a resource, or 86400000 (1 day) as default
+   * 
+   * @return a number of ms to cache a resource. The default is 86400000 (1 day)
+   */
+  public long getCacheTimeout() 
+  {
+	if (getPluginPreferences().contains(PreferenceConstants.CACHE_DURATION)) {
+		long l = getPluginPreferences().getLong(PreferenceConstants.CACHE_DURATION); 
+		if( l > 0 )
+			return l;
+	}
+	// 1 day
+	return 86400000;
+  }
+
+  
   static boolean isRunning() {
 	  return plugin != null;
   }
diff --git a/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/CachePluginResources.properties b/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/CachePluginResources.properties
index 6dc881a..6409ec4 100644
--- a/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/CachePluginResources.properties
+++ b/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/CachePluginResources.properties
@@ -18,6 +18,8 @@
 _UI_BUTTON_DELETE_ENTRY                          = &Remove
 _UI_PREF_CACHE_ENTRIES_TITLE                     = &Cache entries:
 _UI_PREF_CACHE_CACHE_OPTION                      = &Disable caching
+_UI_PREF_CACHE_IGNORE_NO_CACHE_HEADER            = Ignore no-cache header (always cache)
+_UI_PREF_CACHE_CACHE_DURATION_LABEL              = Cache Duration (ms): 
 _UI_PREF_CACHE_ABOUT                             = Manage the cache of remote resources, such as those downloaded from the internet.
 _UI_PREF_PROMPT_FOR_DISAGREED_LICENSES           = &Prompt me for agreement for licenses for whose terms I have already disagreed
 
diff --git a/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/preferences/CachePreferencePage.java b/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/preferences/CachePreferencePage.java
index 4ac9667..82119d8 100644
--- a/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/preferences/CachePreferencePage.java
+++ b/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/preferences/CachePreferencePage.java
@@ -16,6 +16,8 @@
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.jface.preference.PreferencePage;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.events.SelectionListener;
@@ -27,6 +29,7 @@
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Text;
 import org.eclipse.ui.IWorkbench;
 import org.eclipse.ui.IWorkbenchPreferencePage;
 import org.eclipse.ui.PlatformUI;
@@ -49,7 +52,11 @@
   protected Button deleteButton;
 
   protected Button enabledButton;
-  
+
+  protected Button ignoreNoCacheButton;
+
+  protected Text cacheDuration;
+
   protected Button disagreedLicensesButton;
 
   protected List entries;
@@ -109,31 +116,52 @@
     new Label(composite, SWT.None);
     try
     {
-      // Created the disable cache option.
-      enabledButton = new Button(composite, SWT.CHECK | SWT.LEFT);
-      gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
-      gridData.horizontalSpan = 2;
-      enabledButton.setLayoutData(gridData);
-      enabledButton.setText(CacheMessages._UI_PREF_CACHE_CACHE_OPTION);
-      enabledButton.setSelection(!CachePlugin.getDefault().getPreferenceStore()
-          .getBoolean(PreferenceConstants.CACHE_ENABLED));
-      enabledButton.addSelectionListener(new SelectionListener()
-      {
-
-        public void widgetDefaultSelected(SelectionEvent e)
+        // Created the disable cache option.
+        enabledButton = new Button(composite, SWT.CHECK | SWT.LEFT);
+        gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+        gridData.horizontalSpan = 2;
+        enabledButton.setLayoutData(gridData);
+        enabledButton.setText(CacheMessages._UI_PREF_CACHE_CACHE_OPTION);
+        enabledButton.setSelection(!CachePlugin.getDefault().getPreferenceStore()
+            .getBoolean(PreferenceConstants.CACHE_ENABLED));
+        enabledButton.addSelectionListener(new SelectionListener()
         {
-          widgetSelected(e);
 
-        }
+          public void widgetDefaultSelected(SelectionEvent e)
+          {
+            widgetSelected(e);
 
-        public void widgetSelected(SelectionEvent e)
-        {
-          boolean disabled = enabledButton.getSelection();
-          CachePlugin.getDefault().setCacheEnabled(!disabled);
-        }
+          }
 
-      });
-      
+          public void widgetSelected(SelectionEvent e)
+          {
+            boolean disabled = enabledButton.getSelection();
+            CachePlugin.getDefault().setCacheEnabled(!disabled);
+          }
+
+        });
+        
+        
+        
+        // Created the ignore no-cache header option.
+        ignoreNoCacheButton = new Button(composite, SWT.CHECK | SWT.LEFT);
+        gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+        gridData.horizontalSpan = 2;
+        ignoreNoCacheButton.setLayoutData(gridData);
+        ignoreNoCacheButton.setText(CacheMessages._UI_PREF_CACHE_IGNORE_NO_CACHE_HEADER);
+        ignoreNoCacheButton.setSelection(CachePlugin.getDefault().isIgnoreNoCacheHeader());
+        ignoreNoCacheButton.addSelectionListener(new SelectionListener() {
+          public void widgetDefaultSelected(SelectionEvent e) {
+            widgetSelected(e);
+          }
+          public void widgetSelected(SelectionEvent e) {
+            boolean ignoreNoCacheHeader = ignoreNoCacheButton.getSelection();
+            CachePlugin.getDefault().setIgnoreNoCacheHeader(ignoreNoCacheHeader);
+          }
+        });
+
+        
+        
       disagreedLicensesButton = new Button(composite, SWT.CHECK | SWT.LEFT);
       gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
       gridData.horizontalSpan = 2;
@@ -157,6 +185,33 @@
         }
 
       });
+      
+      
+      // Created the cache duration setting
+      Composite durationWrapper = new Composite(composite, SWT.NONE);
+      gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+      gridData.horizontalSpan = 2;
+      durationWrapper.setLayoutData(gridData);
+      GridLayout gl = new GridLayout(2, false);
+      durationWrapper.setLayout(gl);
+      
+      Label cacheDurationLabel = new Label(durationWrapper, SWT.NONE);
+      cacheDurationLabel.setText(CacheMessages._UI_PREF_CACHE_CACHE_DURATION_LABEL);
+      gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+      cacheDurationLabel.setLayoutData(gridData);
+      
+      cacheDuration = new Text(durationWrapper, SWT.BORDER | SWT.LEFT);
+      gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+      cacheDuration.setLayoutData(gridData);
+      cacheDuration.setText(Long.toString(CachePlugin.getDefault().getCacheTimeout()));
+      cacheDuration.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+	            CachePlugin.getDefault().setCacheTimeout(Long.parseLong(cacheDuration.getText()));
+			}
+      });
+      
+
+      
 
       // Create the entities group.
       Label entriesLabel = new Label(composite, SWT.WRAP);
diff --git a/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/preferences/PreferenceConstants.java b/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/preferences/PreferenceConstants.java
index a51c4ae..a554eae 100644
--- a/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/preferences/PreferenceConstants.java
+++ b/plugins/org.eclipse.wst.internet.cache/src/org/eclipse/wst/internet/cache/internal/preferences/PreferenceConstants.java
@@ -14,10 +14,12 @@
 /**
  * Constant definitions for plug-in preferences
  */
-public class PreferenceConstants 
-{
-  public static final String CACHE_ENABLED = "cacheEnabled";
-  
-  public static final String PROMPT_DISAGREED_LICENSES = "promptDisagreedLicenses";
-	
+public class PreferenceConstants  {
+	  public static final String CACHE_ENABLED = "cacheEnabled";
+
+	  public static final String IGNORE_NO_CACHE_HEADER = "ignoreNoCacheHeader";
+
+	  public static final String CACHE_DURATION = "cacheDuration";
+
+	  public static final String PROMPT_DISAGREED_LICENSES = "promptDisagreedLicenses";
 }