Use VersionTable to reduce memory foot print and Object creation (FELIX-2085)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@910893 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/sigil/common/core/src/org/apache/felix/sigil/config/BldConverter.java b/sigil/common/core/src/org/apache/felix/sigil/config/BldConverter.java
index dcfde4b..176b79f 100644
--- a/sigil/common/core/src/org/apache/felix/sigil/config/BldConverter.java
+++ b/sigil/common/core/src/org/apache/felix/sigil/config/BldConverter.java
@@ -32,6 +32,7 @@
 import java.util.regex.Pattern;
 
 import org.apache.felix.sigil.common.osgi.VersionRange;
+import org.apache.felix.sigil.common.osgi.VersionTable;
 import org.apache.felix.sigil.config.IBldProject.IBldBundle;
 import org.apache.felix.sigil.core.BldCore;
 import org.apache.felix.sigil.core.internal.model.eclipse.SigilBundle;
@@ -43,7 +44,6 @@
 import org.apache.felix.sigil.model.osgi.IRequiredBundle;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.Path;
-import org.osgi.framework.Version;
 
 import aQute.lib.osgi.Constants;
 
@@ -155,7 +155,7 @@
 
         info.setSymbolicName( bundle.getSymbolicName() );
 
-        info.setVersion( Version.parseVersion( bundle.getVersion() ) );
+        info.setVersion( VersionTable.getVersion( bundle.getVersion() ) );
 
         String activator = bundle.getActivator();
         if ( activator != null )
diff --git a/sigil/common/core/src/org/apache/felix/sigil/config/BldProject.java b/sigil/common/core/src/org/apache/felix/sigil/config/BldProject.java
index 7f024d5..8e5ff65 100644
--- a/sigil/common/core/src/org/apache/felix/sigil/config/BldProject.java
+++ b/sigil/common/core/src/org/apache/felix/sigil/config/BldProject.java
@@ -42,6 +42,7 @@
 import java.util.TreeSet;
 
 import org.apache.felix.sigil.common.osgi.VersionRange;
+import org.apache.felix.sigil.common.osgi.VersionTable;
 import org.apache.felix.sigil.core.internal.model.osgi.BundleModelElement;
 import org.apache.felix.sigil.core.internal.model.osgi.PackageExport;
 import org.apache.felix.sigil.core.internal.model.osgi.PackageImport;
@@ -53,7 +54,6 @@
 import org.apache.felix.sigil.model.osgi.IPackageImport;
 import org.apache.felix.sigil.model.osgi.IPackageImport.OSGiImport;
 import org.apache.felix.sigil.model.osgi.IRequiredBundle;
-import org.osgi.framework.Version;
 
 public class BldProject implements IBldProject, IRepositoryConfig
 {
@@ -888,7 +888,7 @@
                     }
 
                     if (version != null)
-                        pkgExport.setVersion(new Version(version));
+                        pkgExport.setVersion(VersionTable.getVersion(version));
 
                     list.add(pkgExport);
                 }
diff --git a/sigil/common/core/src/org/apache/felix/sigil/repository/AbstractBundleRepository.java b/sigil/common/core/src/org/apache/felix/sigil/repository/AbstractBundleRepository.java
index dbd81ad..ef6aa67 100644
--- a/sigil/common/core/src/org/apache/felix/sigil/repository/AbstractBundleRepository.java
+++ b/sigil/common/core/src/org/apache/felix/sigil/repository/AbstractBundleRepository.java
@@ -30,6 +30,7 @@
 import java.util.jar.Manifest;
 
 import org.apache.felix.sigil.common.osgi.VersionRange;
+import org.apache.felix.sigil.common.osgi.VersionTable;
 import org.apache.felix.sigil.core.BldCore;
 import org.apache.felix.sigil.core.licence.ILicenseManager;
 import org.apache.felix.sigil.core.licence.ILicensePolicy;
@@ -298,7 +299,7 @@
                 {
                     info = ModelElementFactory.getInstance().newModelElement( IBundleModelElement.class );
                     info.setSymbolicName( name.split( ";" )[0] );
-                    info.setVersion( Version.parseVersion( attrs.getValue( "Bundle-Version" ) ) );
+                    info.setVersion( VersionTable.getVersion( attrs.getValue( "Bundle-Version" ) ) );
                     info.setName( attrs.getValue( "Bundle-Name" ) );
                     info.setDescription( attrs.getValue( "Bundle-Description" ) );
                     info.setVendor( attrs.getValue( "Bundle-Vendor" ) );
@@ -433,7 +434,7 @@
     private Version parseVersion( String val )
     {
         val = val.replaceAll( "\"", "" );
-        return new Version( val );
+        return VersionTable.getVersion( val );
     }
 
 
diff --git a/sigil/common/obr/src/org/apache/felix/sigil/obr/impl/OBRHandler.java b/sigil/common/obr/src/org/apache/felix/sigil/obr/impl/OBRHandler.java
index 8646bba..19b0aab 100644
--- a/sigil/common/obr/src/org/apache/felix/sigil/obr/impl/OBRHandler.java
+++ b/sigil/common/obr/src/org/apache/felix/sigil/obr/impl/OBRHandler.java
@@ -34,6 +34,7 @@
 import org.apache.felix.sigil.common.osgi.LDAPParser;
 import org.apache.felix.sigil.common.osgi.SimpleTerm;
 import org.apache.felix.sigil.common.osgi.VersionRange;
+import org.apache.felix.sigil.common.osgi.VersionTable;
 import org.apache.felix.sigil.model.ModelElementFactory;
 import org.apache.felix.sigil.model.eclipse.ISigilBundle;
 import org.apache.felix.sigil.model.osgi.IBundleModelElement;
@@ -42,7 +43,6 @@
 import org.apache.felix.sigil.model.osgi.IRequiredBundle;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.Path;
-import org.osgi.framework.Version;
 import org.xml.sax.Attributes;
 import org.xml.sax.Locator;
 import org.xml.sax.SAXException;
@@ -143,7 +143,7 @@
                 IBundleModelElement info = ModelElementFactory.getInstance()
                     .newModelElement( IBundleModelElement.class );
                 info.setSymbolicName( attributes.getValue( "", SYMBOLIC_NAME ) );
-                info.setVersion( new Version( attributes.getValue( "", VERSION ) ) );
+                info.setVersion( VersionTable.getVersion(attributes.getValue( "", VERSION ) ) );
                 info.setName( attributes.getValue( "", PRESENTATION_NAME ) );
                 URI l = makeAbsolute( uri );
                 info.setUpdateLocation( l );
@@ -284,7 +284,7 @@
             }
             else if ( "version".equals( name ) )
             {
-                export.setVersion( new Version( value ) );
+                export.setVersion( VersionTable.getVersion( value ) );
             }
         }
     }
diff --git a/sigil/common/obr/src/org/apache/felix/sigil/obr/impl/VersionRangeHelper.java b/sigil/common/obr/src/org/apache/felix/sigil/obr/impl/VersionRangeHelper.java
index bf72f64..f25babb 100644
--- a/sigil/common/obr/src/org/apache/felix/sigil/obr/impl/VersionRangeHelper.java
+++ b/sigil/common/obr/src/org/apache/felix/sigil/obr/impl/VersionRangeHelper.java
@@ -30,6 +30,7 @@
 import org.apache.felix.sigil.common.osgi.Ops;
 import org.apache.felix.sigil.common.osgi.SimpleTerm;
 import org.apache.felix.sigil.common.osgi.VersionRange;
+import org.apache.felix.sigil.common.osgi.VersionTable;
 import org.osgi.framework.Version;
 
 
@@ -178,7 +179,7 @@
 
     private static Version toVersion( SimpleTerm t )
     {
-        return new Version( t.getRval() );
+        return VersionTable.getVersion( t.getRval() );
     }
 
 
diff --git a/sigil/common/osgi/src/org/apache/felix/sigil/common/osgi/VersionRange.java b/sigil/common/osgi/src/org/apache/felix/sigil/common/osgi/VersionRange.java
index a4a1558..321f4e2 100644
--- a/sigil/common/osgi/src/org/apache/felix/sigil/common/osgi/VersionRange.java
+++ b/sigil/common/osgi/src/org/apache/felix/sigil/common/osgi/VersionRange.java
@@ -97,7 +97,7 @@
         }
         else
         {
-            Version atLeast = Version.parseVersion( val );
+            Version atLeast = VersionTable.getVersion( val );
             return new VersionRange( atLeast );
         }
 
@@ -122,7 +122,7 @@
         {
             throw new IllegalArgumentException( "illegal version range syntax " + "too many commas" );
         }
-        Version floor = Version.parseVersion( floorCeiling[0] );
+        Version floor = VersionTable.getVersion( floorCeiling[0] );
         Version ceiling = "*".equals( floorCeiling[1] ) ? INFINITE_VERSION : Version.parseVersion( floorCeiling[1] );
         return new VersionRange( openFloor, floor, ceiling, openCeiling );
     }
@@ -260,16 +260,16 @@
         switch ( lowerBoundRule )
         {
             case Any:
-                floor = new Version( 0, 0, 0 );
+                floor = VersionTable.getVersion( 0, 0, 0 );
                 break;
             case Major:
-                floor = new Version( pointVersion.getMajor(), 0, 0 );
+                floor = VersionTable.getVersion( pointVersion.getMajor(), 0, 0 );
                 break;
             case Minor:
-                floor = new Version( pointVersion.getMajor(), pointVersion.getMinor(), 0 );
+                floor = VersionTable.getVersion( pointVersion.getMajor(), pointVersion.getMinor(), 0 );
                 break;
             case Micro:
-                floor = new Version( pointVersion.getMajor(), pointVersion.getMinor(), pointVersion.getMicro() );
+                floor = VersionTable.getVersion( pointVersion.getMajor(), pointVersion.getMinor(), pointVersion.getMicro() );
                 break;
             case Exact:
                 floor = pointVersion;
@@ -284,13 +284,13 @@
                 ceiling = INFINITE_VERSION;
                 break;
             case Major:
-                ceiling = new Version( pointVersion.getMajor() + 1, 0, 0 );
+                ceiling = VersionTable.getVersion( pointVersion.getMajor() + 1, 0, 0 );
                 break;
             case Minor:
-                ceiling = new Version( pointVersion.getMajor(), pointVersion.getMinor() + 1, 0 );
+                ceiling = VersionTable.getVersion( pointVersion.getMajor(), pointVersion.getMinor() + 1, 0 );
                 break;
             case Micro:
-                ceiling = new Version( pointVersion.getMajor(), pointVersion.getMinor(), pointVersion.getMicro() + 1 );
+                ceiling = VersionTable.getVersion( pointVersion.getMajor(), pointVersion.getMinor(), pointVersion.getMicro() + 1 );
                 break;
             case Exact:
                 ceiling = pointVersion;
diff --git a/sigil/common/osgi/src/org/apache/felix/sigil/common/osgi/VersionTable.java b/sigil/common/osgi/src/org/apache/felix/sigil/common/osgi/VersionTable.java
new file mode 100644
index 0000000..1fb5565
--- /dev/null
+++ b/sigil/common/osgi/src/org/apache/felix/sigil/common/osgi/VersionTable.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.sigil.common.osgi;
+
+import java.util.WeakHashMap;
+
+import org.osgi.framework.Version;
+
+/**
+ * Cache of Versions used in Sigil backed by a WeakHashMap to conserve memory.
+ * 
+ * VersionTable.getVersion should be used in preference to new Version() or Version.parseVersion.
+ * 
+ * @author dave
+ *
+ */
+public class VersionTable
+{
+    private static final WeakHashMap<String, Version> versions = new WeakHashMap<String, Version>();
+    
+    public static Version getVersion(String version) {
+        synchronized( versions ) {
+            Version v = versions.get(version);
+            if ( v == null ) {
+                v = Version.parseVersion(version);
+                versions.put(version, v);
+            }
+            
+            return v;
+        }
+    }
+    
+    public static Version getVersion(int major, int minor, int micro) {
+        return getVersion(major, minor, micro, null);
+    }
+
+    public static Version getVersion(int major, int minor, int micro, String qualifier) {
+        String key;
+        
+        if ( qualifier == null ) {
+            key = major + "." + minor + "." + micro;
+        }
+        else {
+            assert qualifier.trim().length() > 0;
+            key = major + "." + minor + "." + micro + "." + qualifier;            
+        }
+        
+        synchronized( versions ) {
+            Version v = versions.get(key);
+            if ( v == null ) {
+                v = new Version(major, minor, micro);
+                versions.put(key, v);
+            }
+            
+            return v;
+        }
+    }
+}
diff --git a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/GeneralInfoSection.java b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/GeneralInfoSection.java
index 8cb74e1..7cc61f8 100644
--- a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/GeneralInfoSection.java
+++ b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/GeneralInfoSection.java
@@ -20,6 +20,7 @@
 package org.apache.felix.sigil.ui.eclipse.ui.editors.project;
 
 
+import org.apache.felix.sigil.common.osgi.VersionTable;
 import org.apache.felix.sigil.eclipse.model.project.ISigilProjectModel;
 import org.apache.felix.sigil.model.ModelElementFactory;
 import org.apache.felix.sigil.model.eclipse.ISigilBundle;
@@ -134,7 +135,7 @@
 
             public Object getValue( String label )
             {
-                return Version.parseVersion( label );
+                return VersionTable.getVersion( label );
             }
         };
 
diff --git a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/NewPackageExportDialog.java b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/NewPackageExportDialog.java
index 6558114..cefa091 100644
--- a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/NewPackageExportDialog.java
+++ b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/NewPackageExportDialog.java
@@ -22,6 +22,7 @@
 
 import java.util.Comparator;
 
+import org.apache.felix.sigil.common.osgi.VersionTable;
 import org.apache.felix.sigil.ui.eclipse.ui.util.BackgroundLoadingSelectionDialog;
 import org.apache.felix.sigil.ui.eclipse.ui.util.IElementDescriptor;
 import org.eclipse.jdt.core.IPackageFragment;
@@ -67,7 +68,7 @@
 
     private Version version = null;
     private String error = null;
-    private Version projectVersion = new Version( 0, 0, 0 );
+    private Version projectVersion = VersionTable.getVersion( 0, 0, 0 );
 
     private Button btnInheritBundleVersion;
     private Button btnExplicitVersion;
@@ -130,7 +131,7 @@
                     txtVersion.setEnabled( true );
                     try
                     {
-                        version = new Version( txtVersion.getText() );
+                        version = VersionTable.getVersion( txtVersion.getText() );
                     }
                     catch ( IllegalArgumentException e )
                     {
diff --git a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/PackageExportDialog.java b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/PackageExportDialog.java
index 246b2a3..42f2f58 100644
--- a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/PackageExportDialog.java
+++ b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/PackageExportDialog.java
@@ -20,6 +20,7 @@
 package org.apache.felix.sigil.ui.eclipse.ui.editors.project;
 
 
+import org.apache.felix.sigil.common.osgi.VersionTable;
 import org.eclipse.jface.viewers.IContentProvider;
 import org.eclipse.jface.viewers.ViewerFilter;
 import org.eclipse.swt.SWT;
@@ -59,7 +60,7 @@
             {
                 try
                 {
-                    version = Version.parseVersion( versionText.getText() );
+                    version = VersionTable.getVersion( versionText.getText() );
                     setErrorMessage( null );
                 }
                 catch ( IllegalArgumentException ex )
diff --git a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/VersionRangeComponent.java b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/VersionRangeComponent.java
index d38578b..a99640b 100644
--- a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/VersionRangeComponent.java
+++ b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/editors/project/VersionRangeComponent.java
@@ -24,6 +24,7 @@
 import java.util.Set;
 
 import org.apache.felix.sigil.common.osgi.VersionRange;
+import org.apache.felix.sigil.common.osgi.VersionTable;
 import org.apache.felix.sigil.ui.eclipse.ui.util.IValidationListener;
 import org.eclipse.jface.dialogs.IMessageProvider;
 import org.eclipse.swt.SWT;
@@ -254,15 +255,14 @@
                 }
                 else
                 {
-                    Version v = Version.parseVersion( specificText.getText().trim() );
+                    Version v = VersionTable.getVersion( specificText.getText().trim() );
                     versions = new VersionRange( false, v, v, false );
                 }
             }
             else
             {
-                Version min = Version.parseVersion( minimumText.getText() );
-                Version max = "*".equals( maximumText.getText() ) ? VersionRange.INFINITE_VERSION : Version
-                    .parseVersion( maximumText.getText() );
+                Version min = VersionTable.getVersion( minimumText.getText() );
+                Version max = "*".equals( maximumText.getText() ) ? VersionRange.INFINITE_VERSION : VersionTable.getVersion( maximumText.getText() );
                 versions = new VersionRange( !minInclusiveButton.getSelection(), min, max, !maxInclusiveButton
                     .getSelection() );
             }
diff --git a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/preferences/LibraryConfigurationDialog.java b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/preferences/LibraryConfigurationDialog.java
index 1c1584f..32770ce 100644
--- a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/preferences/LibraryConfigurationDialog.java
+++ b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/preferences/LibraryConfigurationDialog.java
@@ -24,6 +24,7 @@
 import java.util.Iterator;
 import java.util.TreeSet;
 
+import org.apache.felix.sigil.common.osgi.VersionTable;
 import org.apache.felix.sigil.model.ModelElementFactory;
 import org.apache.felix.sigil.model.eclipse.ILibrary;
 import org.apache.felix.sigil.model.osgi.IPackageImport;
@@ -224,7 +225,7 @@
 
         try
         {
-            version = new Version( txtVersion.getText() );
+            version = VersionTable.getVersion( txtVersion.getText() );
             if ( version.getQualifier().indexOf( '_' ) > -1 )
             {
                 warning = "The use of underscores in a version qualifier is discouraged.";
diff --git a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/preferences/VersionsPreferencePage.java b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/preferences/VersionsPreferencePage.java
index 1ec4892..846f764 100644
--- a/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/preferences/VersionsPreferencePage.java
+++ b/sigil/eclipse/ui/src/org/apache/felix/sigil/ui/eclipse/ui/preferences/VersionsPreferencePage.java
@@ -22,8 +22,8 @@
 
 import org.apache.felix.sigil.common.osgi.VersionRange;
 import org.apache.felix.sigil.common.osgi.VersionRangeBoundingRule;
+import org.apache.felix.sigil.common.osgi.VersionTable;
 import org.apache.felix.sigil.eclipse.SigilCore;
-import org.apache.felix.sigil.ui.eclipse.ui.SigilUI;
 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.preference.PreferencePage;
 import org.eclipse.swt.SWT;
@@ -31,7 +31,6 @@
 import org.eclipse.swt.events.ModifyListener;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Button;
@@ -48,7 +47,7 @@
 public class VersionsPreferencePage extends PreferencePage implements IWorkbenchPreferencePage
 {
 
-    private static final Version SAMPLE_VERSION = new Version( 1, 2, 3, "qualifier" );
+    private static final Version SAMPLE_VERSION = VersionTable.getVersion( 1, 2, 3, "qualifier" );
 
     private IWorkbench workbench;
 
@@ -169,7 +168,7 @@
             {
                 try
                 {
-                    sampleVersion = new Version( txtSampleVersion.getText() );
+                    sampleVersion = VersionTable.getVersion( txtSampleVersion.getText() );
                 }
                 catch ( IllegalArgumentException x )
                 {
@@ -184,7 +183,7 @@
             {
                 try
                 {
-                    matchVersion = new Version( txtMatchVersion.getText() );
+                    matchVersion = VersionTable.getVersion( txtMatchVersion.getText() );
                 }
                 catch ( IllegalArgumentException x )
                 {
diff --git a/sigil/ivy/resolver/src/org/apache/felix/sigil/ivy/ProjectRepository.java b/sigil/ivy/resolver/src/org/apache/felix/sigil/ivy/ProjectRepository.java
index 73a992c..2f9e58a 100644
--- a/sigil/ivy/resolver/src/org/apache/felix/sigil/ivy/ProjectRepository.java
+++ b/sigil/ivy/resolver/src/org/apache/felix/sigil/ivy/ProjectRepository.java
@@ -30,6 +30,7 @@
 import java.util.Map;
 
 import org.apache.felix.sigil.common.osgi.VersionRange;
+import org.apache.felix.sigil.common.osgi.VersionTable;
 import org.apache.felix.sigil.config.BldFactory;
 import org.apache.felix.sigil.config.IBldProject;
 import org.apache.felix.sigil.config.IBldProject.IBldBundle;
@@ -270,7 +271,7 @@
 
             info.setSymbolicName(bb.getSymbolicName());
 
-            Version version = new Version(bb.getVersion());
+            Version version = VersionTable.getVersion(bb.getVersion());
             info.setVersion(version);
 
             ISigilBundle pb = ModelElementFactory.getInstance().newModelElement(ISigilBundle.class);