[Title] added ZipEditor to org.tizen.common.externals & added Tizen package files... 64/10764/5
authorGun Kim <gune.kim@samsung.com>
Fri, 11 Oct 2013 07:41:34 +0000 (16:41 +0900)
committerGun Kim <gune.kim@samsung.com>
Tue, 15 Oct 2013 06:07:47 +0000 (15:07 +0900)
[Type]
[Module]
[Priority]
[Jira#]
[Redmine#]
[Problem]
[Cause]
[Solution]
[TestCase]

Change-Id: I96653780de9d59f8a941d57d592df92931c02bed
Signed-off-by: Gun Kim <gune.kim@samsung.com>
97 files changed:
LICENSE.CPLv1 [new file with mode: 0644]
NOTICE
org.tizen.common.externals/META-INF/MANIFEST.MF
org.tizen.common.externals/OSGI-INF/l10n/bundle.properties
org.tizen.common.externals/about.html
org.tizen.common.externals/about_files/LICENSE.CPLv1 [new file with mode: 0644]
org.tizen.common.externals/build.properties
org.tizen.common.externals/icons/add.gif [new file with mode: 0644]
org.tizen.common.externals/icons/alphab_sort_co.gif [new file with mode: 0644]
org.tizen.common.externals/icons/arrow_down.gif [new file with mode: 0644]
org.tizen.common.externals/icons/collapseall.gif [new file with mode: 0644]
org.tizen.common.externals/icons/expandall.gif [new file with mode: 0644]
org.tizen.common.externals/icons/extract.gif [new file with mode: 0644]
org.tizen.common.externals/icons/sort_asc.gif [new file with mode: 0644]
org.tizen.common.externals/icons/sort_desc.gif [new file with mode: 0644]
org.tizen.common.externals/icons/sort_none.gif [new file with mode: 0644]
org.tizen.common.externals/icons/synced.gif [new file with mode: 0644]
org.tizen.common.externals/icons/togglemode.gif [new file with mode: 0644]
org.tizen.common.externals/icons/tpk.png [new file with mode: 0755]
org.tizen.common.externals/icons/wgt.png [new file with mode: 0755]
org.tizen.common.externals/icons/zipicon.gif [new file with mode: 0644]
org.tizen.common.externals/plugin.xml [new file with mode: 0644]
org.tizen.common.externals/src/org/tizen/common/externals/ExternalsPlugin.java
org.tizen.common.externals/src/org/tizen/common/externals/navigatorContent/PackageActionProvider.java [new file with mode: 0644]
org.tizen.common.externals/src/org/tizen/common/externals/navigatorContent/PackageContentProvider.java [new file with mode: 0644]
org.tizen.common.externals/src/org/tizen/common/externals/navigatorContent/PackageLabelProvider.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/LocalFileEditorInput.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/Messages.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/MultiElementPropertyPage.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/MultiPreferenceDialog.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/NodePropertyPage.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/PreferenceConstants.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/PreferenceInitializer.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/TableFrame.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/TableViewerFrameSource.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/TarNodePropertyPage.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/Utils.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/ZipContentProvider.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/ZipEditor.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/ZipEditorActionBarContributor.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/ZipEditorDragAdapter.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/ZipEditorDropAdapter.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/ZipEditorPlugin.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/ZipLabelProvider.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/ZipNodePropertyPage.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/ZipOutlinePage.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/ZipSorter.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/ActionMessages.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/ActionMessages.properties [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/AddAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/CollapseAllAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/CopyAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/DeferredMenuManager.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/DeleteAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/DialogAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/EditorAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/ExtractAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/FileOpener.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/MostRecentlyUsedMenu.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/MultiPropertyDialogAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/NewFolderAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/OpenAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/OpenActionGroup.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/OpenWithMenu.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/PreferencesAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/RenameNodeAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/ReverseSelectionAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/RevertAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/SaveAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/SelectAllAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/SelectPatternAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/SortAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/StringMatcher.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/TogglePreferenceAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/ToggleStoreFoldersAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/ToggleViewModeAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/ViewerAction.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/ZipActionGroup.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/actions/ZipActionProvider.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/messages.properties [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/model/Bzip2Node.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/model/FileAdapter.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/model/GzipNode.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/model/IModelListener.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/model/Node.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/model/NodeProperty.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/model/NodeWorkbenchAdapter.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/model/TarNode.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/model/TarNodeProperty.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/model/ZipContentDescriber.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/model/ZipModel.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/model/ZipNode.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/model/ZipNodeProperty.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/operations/AddOperation.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/operations/ExtractOperation.java [new file with mode: 0644]
org.tizen.common.externals/src/zipeditor/operations/OpenFileOperation.java [new file with mode: 0644]
org.tizen.common/src/org/tizen/common/TizenPlatformConstants.java

diff --git a/LICENSE.CPLv1 b/LICENSE.CPLv1
new file mode 100644 (file)
index 0000000..1c13794
--- /dev/null
@@ -0,0 +1,86 @@
+Common Public License Version 1.0
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 
+
+1. DEFINITIONS 
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and 
+
+b) in the case of each subsequent Contributor:
+
+i) changes to the Program, and
+
+ii) additions to the Program;
+
+where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program. 
+
+"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this Agreement. 
+
+"Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 
+
+2. GRANT OF RIGHTS
+
+a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
+
+b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
+
+c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
+
+d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.
+
+3. REQUIREMENTS 
+
+A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: 
+
+a) it complies with the terms and conditions of this Agreement; and
+
+b) its license agreement:
+
+i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; 
+
+ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; 
+
+iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and 
+
+iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. 
+
+When the Program is made available in source code form:
+
+a) it must be made available under this Agreement; and
+
+b) a copy of this Agreement must be included with each copy of the Program. 
+
+Contributors may not remove or alter any copyright notices contained within the Program.
+
+Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 
+
+4. COMMERCIAL DISTRIBUTION 
+
+Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. 
+
+For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 
+
+6. DISCLAIMER OF LIABILITY 
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. 
+
+If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. 
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. 
+
+This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.
diff --git a/NOTICE b/NOTICE
index cd5849d..3102ff1 100644 (file)
--- a/NOTICE
+++ b/NOTICE
@@ -84,3 +84,10 @@ Notices for file(s):
 ------------------------------------------------------------
 Apache License, Version 2.0
 http://commons.apache.org/proper/commons-math/
+
+============================================================
+Notices for file(s):
+/org.tizen.common.externals/src/zipeditor/*
+------------------------------------------------------------
+Common Public License, Version 1.0
+http://zipeditor.sourceforge.net/
index 278ae89..92492f2 100644 (file)
@@ -1,12 +1,13 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name
-Bundle-SymbolicName: org.tizen.common.externals
+Bundle-SymbolicName: org.tizen.common.externals;singleton:=true
 Bundle-Version: 2.0.0.qualifier
 Bundle-Activator: org.tizen.common.externals.ExternalsPlugin
 Bundle-Vendor: %Bundle-Vendor
 Require-Bundle: org.eclipse.ui,
- org.eclipse.core.runtime
+ org.eclipse.core.runtime,
+ org.eclipse.ui.ide
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
 Bundle-ActivationPolicy: lazy
 Export-Package: com.tinkerpop.blueprints,
@@ -40,8 +41,7 @@ Export-Package: com.tinkerpop.blueprints,
  org.mihalis.opal.tipOfTheDay,
  org.mihalis.opal.titledSeparator,
  org.mihalis.opal.transitionComposite,
- org.mihalis.opal.utils,
- org.tizen.common.externals
+ org.mihalis.opal.utils
 Bundle-ClassPath: orientdb_lib/antlr-2.7.7.jar,
  orientdb_lib/asm-3.2.jar,
  orientdb_lib/blueprints-core-2.5.0-SNAPSHOT.jar,
@@ -75,3 +75,16 @@ Bundle-ClassPath: orientdb_lib/antlr-2.7.7.jar,
  orientdb_lib/sesame-sail-api-2.6.10.jar,
  orientdb_lib/snappy-0.3.jar,
  .
+Import-Package: org.apache.tools.bzip2,
+ org.apache.tools.tar,
+ org.eclipse.core.filesystem,
+ org.eclipse.core.resources,
+ org.eclipse.ui,
+ org.eclipse.ui.editors.text,
+ org.eclipse.ui.navigator,
+ org.eclipse.ui.texteditor,
+ org.eclipse.ui.views.contentoutline,
+ org.eclipse.ui.views.framelist,
+ org.slf4j,
+ org.tizen.common,
+ org.tizen.common.util
index f342c89..e336866 100644 (file)
@@ -1,3 +1,20 @@
 #Properties file for org.tizen.web.project.wizard
 Bundle-Vendor = The Linux Foundation
-Bundle-Name = Tizen Common Externals
\ No newline at end of file
+Bundle-Name = Tizen Common Externals
+
+# properties file for ZipEditor
+Bundle-Vendor.0 = Uwe Voigt
+Bundle-Name.0 = ZipEditor Plug-in
+content-type.name.0 = Archive
+content-type.name.1 = Zip archive
+content-type.name.2 = Tar GZ archive
+content-type.name.3 = Tar archive
+content-type.name.4 = GZip archive
+content-type.name.5 = BZIP2 archive
+content-type.name.6 = Tar BZIP2 archive
+editor.name.0 = ZipEditor
+navigatorContent.name.0 = Zip Archives
+page.name.0 = Zip element
+page.name.1 = Tar element
+command.name = Select Pattern
+command.name.0 = Reverse Selection
\ No newline at end of file
index a72b377..6b888a5 100644 (file)
@@ -37,5 +37,10 @@ A copy of the license is included in <a href="about_files/epl-v10.html">about_fi
 </ul>
 </p>
 
+<h4>Zip-Editor</h4>
+<p>
+The Zip-Editor is an <a href="http://www.eclipse.org">Eclipse</a> editor that can view and manipulate zip archives.
+</p>
+<p>See <a href="about_files/LICENSE.CPLv1">License</a>.</p>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/org.tizen.common.externals/about_files/LICENSE.CPLv1 b/org.tizen.common.externals/about_files/LICENSE.CPLv1
new file mode 100644 (file)
index 0000000..1c13794
--- /dev/null
@@ -0,0 +1,86 @@
+Common Public License Version 1.0
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 
+
+1. DEFINITIONS 
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and 
+
+b) in the case of each subsequent Contributor:
+
+i) changes to the Program, and
+
+ii) additions to the Program;
+
+where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program. 
+
+"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this Agreement. 
+
+"Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 
+
+2. GRANT OF RIGHTS
+
+a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
+
+b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
+
+c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
+
+d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.
+
+3. REQUIREMENTS 
+
+A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: 
+
+a) it complies with the terms and conditions of this Agreement; and
+
+b) its license agreement:
+
+i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; 
+
+ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; 
+
+iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and 
+
+iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. 
+
+When the Program is made available in source code form:
+
+a) it must be made available under this Agreement; and
+
+b) a copy of this Agreement must be included with each copy of the Program. 
+
+Contributors may not remove or alter any copyright notices contained within the Program.
+
+Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 
+
+4. COMMERCIAL DISTRIBUTION 
+
+Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. 
+
+For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 
+
+6. DISCLAIMER OF LIABILITY 
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. 
+
+If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. 
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. 
+
+This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.
index 40965be..b69b902 100644 (file)
@@ -5,6 +5,9 @@ bin.includes = META-INF/,\
                OSGI-INF/,\\r
                resources/,\\r
                about.html,\\r
-               about_files/,\\r
+               about_files/,\
                images/,\\r
-               orientdb_lib/\r
+               orientdb_lib/,\\r
+               plugin.xml,\\r
+               plugin.properties,\\r
+               icons/
\ No newline at end of file
diff --git a/org.tizen.common.externals/icons/add.gif b/org.tizen.common.externals/icons/add.gif
new file mode 100644 (file)
index 0000000..cc1d670
Binary files /dev/null and b/org.tizen.common.externals/icons/add.gif differ
diff --git a/org.tizen.common.externals/icons/alphab_sort_co.gif b/org.tizen.common.externals/icons/alphab_sort_co.gif
new file mode 100644 (file)
index 0000000..6d77244
Binary files /dev/null and b/org.tizen.common.externals/icons/alphab_sort_co.gif differ
diff --git a/org.tizen.common.externals/icons/arrow_down.gif b/org.tizen.common.externals/icons/arrow_down.gif
new file mode 100644 (file)
index 0000000..70a7d02
Binary files /dev/null and b/org.tizen.common.externals/icons/arrow_down.gif differ
diff --git a/org.tizen.common.externals/icons/collapseall.gif b/org.tizen.common.externals/icons/collapseall.gif
new file mode 100644 (file)
index 0000000..a2d80a9
Binary files /dev/null and b/org.tizen.common.externals/icons/collapseall.gif differ
diff --git a/org.tizen.common.externals/icons/expandall.gif b/org.tizen.common.externals/icons/expandall.gif
new file mode 100644 (file)
index 0000000..0205b29
Binary files /dev/null and b/org.tizen.common.externals/icons/expandall.gif differ
diff --git a/org.tizen.common.externals/icons/extract.gif b/org.tizen.common.externals/icons/extract.gif
new file mode 100644 (file)
index 0000000..b2863ab
Binary files /dev/null and b/org.tizen.common.externals/icons/extract.gif differ
diff --git a/org.tizen.common.externals/icons/sort_asc.gif b/org.tizen.common.externals/icons/sort_asc.gif
new file mode 100644 (file)
index 0000000..155d083
Binary files /dev/null and b/org.tizen.common.externals/icons/sort_asc.gif differ
diff --git a/org.tizen.common.externals/icons/sort_desc.gif b/org.tizen.common.externals/icons/sort_desc.gif
new file mode 100644 (file)
index 0000000..0b0e85f
Binary files /dev/null and b/org.tizen.common.externals/icons/sort_desc.gif differ
diff --git a/org.tizen.common.externals/icons/sort_none.gif b/org.tizen.common.externals/icons/sort_none.gif
new file mode 100644 (file)
index 0000000..c8b090a
Binary files /dev/null and b/org.tizen.common.externals/icons/sort_none.gif differ
diff --git a/org.tizen.common.externals/icons/synced.gif b/org.tizen.common.externals/icons/synced.gif
new file mode 100644 (file)
index 0000000..870934b
Binary files /dev/null and b/org.tizen.common.externals/icons/synced.gif differ
diff --git a/org.tizen.common.externals/icons/togglemode.gif b/org.tizen.common.externals/icons/togglemode.gif
new file mode 100644 (file)
index 0000000..5bc3b01
Binary files /dev/null and b/org.tizen.common.externals/icons/togglemode.gif differ
diff --git a/org.tizen.common.externals/icons/tpk.png b/org.tizen.common.externals/icons/tpk.png
new file mode 100755 (executable)
index 0000000..f9b001f
Binary files /dev/null and b/org.tizen.common.externals/icons/tpk.png differ
diff --git a/org.tizen.common.externals/icons/wgt.png b/org.tizen.common.externals/icons/wgt.png
new file mode 100755 (executable)
index 0000000..84cd309
Binary files /dev/null and b/org.tizen.common.externals/icons/wgt.png differ
diff --git a/org.tizen.common.externals/icons/zipicon.gif b/org.tizen.common.externals/icons/zipicon.gif
new file mode 100644 (file)
index 0000000..2bf853a
Binary files /dev/null and b/org.tizen.common.externals/icons/zipicon.gif differ
diff --git a/org.tizen.common.externals/plugin.xml b/org.tizen.common.externals/plugin.xml
new file mode 100644 (file)
index 0000000..2ae275d
--- /dev/null
@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+    <extension
+         point="org.eclipse.core.contenttype.contentTypes">
+      <content-type
+            id="archive"
+            name="%content-type.name.0"
+            priority="normal"/>
+      <content-type
+            base-type="archive"
+            describer="zipeditor.model.ZipContentDescriber"
+            id="zipfile"
+            name="%content-type.name.1"
+            priority="normal">
+         <property
+               default="ZIP"
+               name="ZipEditor.archiveType"/>
+      </content-type>
+      <content-type
+            base-type="archive"
+            describer="zipeditor.model.ZipContentDescriber"
+            id="targzfile"
+            name="%content-type.name.2"
+            priority="normal">
+         <property
+               default="TGZ"
+               name="ZipEditor.archiveType"/>
+      </content-type>
+      <content-type
+            base-type="archive"
+            describer="zipeditor.model.ZipContentDescriber"
+            id="tarfile"
+            name="%content-type.name.3"
+            priority="normal">
+         <property
+               default="TAR"
+               name="ZipEditor.archiveType"/>
+      </content-type>
+      <content-type
+            base-type="archive"
+            describer="zipeditor.model.ZipContentDescriber"
+            id="gzipfile"
+            name="%content-type.name.4"
+            priority="normal">
+         <property
+               default="GZ"
+               name="ZipEditor.archiveType"/>
+      </content-type>
+      <content-type
+            base-type="archive"
+            describer="zipeditor.model.ZipContentDescriber"
+            id="bz2file"
+            name="%content-type.name.5"
+            priority="normal">
+         <property
+               default="BZ2"
+               name="ZipEditor.archiveType"/>
+      </content-type>
+      <content-type
+            base-type="archive"
+            describer="zipeditor.model.ZipContentDescriber"
+            id="tarbz2file"
+            name="%content-type.name.6"
+            priority="normal">
+         <property
+               default="TBZ"
+               name="ZipEditor.archiveType"/>
+      </content-type>
+      <file-association
+            content-type="org.tizen.common.externals.zipfile"
+            file-extensions="jar, zip, war, ear, tpk, wgt"/>
+      <file-association
+            content-type="org.tizen.common.externals.gzipfile"
+            file-extensions="gz"/>
+      <file-association
+            content-type="org.tizen.common.externals.tarfile"
+            file-extensions="tar"/>
+      <file-association
+            content-type="org.tizen.common.externals.targzfile"
+            file-extensions="tar.gz, tgz"/>
+      <file-association
+            content-type="org.tizen.common.externals.tarbz2file"
+            file-extensions="tar.bz2, tbz"/>
+      <file-association
+            content-type="org.tizen.common.externals.bz2file"
+            file-extensions="bz2"/>
+   </extension>
+   <extension
+         point="org.eclipse.core.runtime.preferences">
+      <initializer class="zipeditor.PreferenceInitializer"/>
+   </extension>
+   <extension
+         point="org.eclipse.ui.editors">
+      <editor
+            class="zipeditor.ZipEditor"
+            contributorClass="zipeditor.ZipEditorActionBarContributor"
+            default="true"
+            icon="icons/zipicon.gif"
+            id="zipeditor.ZipEditor"
+            name="%editor.name.0">
+         <contentTypeBinding contentTypeId="org.tizen.common.externals.zipfile"/>
+         <contentTypeBinding contentTypeId="org.tizen.common.externals.gzipfile"/>
+         <contentTypeBinding contentTypeId="org.tizen.common.externals.tarfile"/>
+         <contentTypeBinding contentTypeId="org.tizen.common.externals.targzfile"/>
+         <contentTypeBinding contentTypeId="org.tizen.common.externals.tarbz2file"/>
+         <contentTypeBinding contentTypeId="org.tizen.common.externals.bz2file"/>
+      </editor>
+   </extension>
+   
+   <extension
+          point="org.eclipse.ui.navigator.navigatorContent">
+       <navigatorContent
+             activeByDefault="true"
+             contentProvider="zipeditor.ZipContentProvider"
+             icon="icons/zipicon.gif"
+             id="zipeditor.navigatorContent"
+             labelProvider="zipeditor.ZipLabelProvider"
+             name="%navigatorContent.name.0"
+             priority="normal">
+          <triggerPoints>
+             <or>
+               <instanceof value="org.eclipse.core.resources.IFile"/>
+               <instanceof value="zipeditor.model.Node"/>
+               <instanceof value="org.eclipse.core.resources.IWorkspaceRoot"/>
+               <instanceof value="org.eclipse.core.resources.IFolder"/>
+               <instanceof value="org.eclipse.core.resources.IProject"/>
+            </or>
+          </triggerPoints>
+          <possibleChildren>
+            <or>
+               <instanceof value="zipeditor.model.Node"/>
+               <instanceof value="org.eclipse.core.resources.IWorkspaceRoot"/>
+               <instanceof value="org.eclipse.core.resources.IFile"/>
+               <instanceof value="org.eclipse.core.resources.IFolder"/>
+               <instanceof value="org.eclipse.core.resources.IProject"/>
+            </or>
+         </possibleChildren>
+         <commonSorter
+               class="zipeditor.ZipSorter"
+               id="zipeditor.ZipSorter">
+            <parentExpression>
+               <or>
+                  <instanceof value="zipeditor.model.Node"/>
+                  <instanceof value="org.eclipse.core.resources.IFile"/>
+               </or>
+            </parentExpression>
+         </commonSorter>
+         <actionProvider
+               class="zipeditor.actions.ZipActionProvider"
+               overrides="org.eclipse.ui.navigator.resources.OpenActions">
+            <enablement>
+               <or>
+                  <instanceof value="zipeditor.model.Node"/>
+                  <instanceof value="org.eclipse.core.resources.IFile"/>
+               </or>
+            </enablement>
+         </actionProvider>
+       </navigatorContent>
+       <navigatorContent
+             activeByDefault="true"
+             contentProvider="org.tizen.common.externals.navigatorContent.PackageContentProvider"
+             icon="icons/wgt.png"
+             id="org.tizen.common.externals.navigatorContent"
+             labelProvider="org.tizen.common.externals.navigatorContent.PackageLabelProvider"
+             name="Tizen Package"
+             priority="higher">
+          <triggerPoints>
+             <and>
+                <adapt
+                      type="org.eclipse.core.resources.IFile">
+                   <or>
+                      <test
+                            property="org.eclipse.core.resources.name"
+                            value="*.wgt">
+                      </test>
+                      <test
+                            property="org.eclipse.core.resources.name"
+                            value="*.tpk">
+                      </test>
+                   </or>
+                </adapt>
+             </and>
+          </triggerPoints>
+          <possibleChildren>
+            <and>
+                <adapt
+                      type="org.eclipse.core.resources.IFile">
+                   <or>
+                      <test
+                            property="org.eclipse.core.resources.name"
+                            value="*.wgt">
+                      </test>
+                      <test
+                            property="org.eclipse.core.resources.name"
+                            value="*.tpk">
+                      </test>
+                   </or>
+                </adapt>
+             </and>
+         </possibleChildren>
+          <actionProvider
+                class="org.tizen.common.externals.navigatorContent.PackageActionProvider"
+                overrides="org.eclipse.ui.navigator.resources.OpenActions">
+             <enablement>
+                <adapt
+                      type="org.eclipse.core.resources.IFile">
+                   <or>
+                      <test
+                            property="org.eclipse.core.resources.name"
+                            value="*.wgt">
+                      </test>
+                      <test
+                            property="org.eclipse.core.resources.name"
+                            value="*.tpk">
+                      </test>
+                   </or>
+                </adapt>
+             </enablement>
+          </actionProvider>
+       </navigatorContent>
+    </extension>
+    <extension
+         point="org.eclipse.ui.navigator.viewer">
+      <viewerContentBinding viewerId="org.eclipse.ui.navigator.ProjectExplorer">
+         <includes>
+            <contentExtension pattern="zipeditor.navigatorContent"/>
+         </includes>
+      </viewerContentBinding>
+      <viewerContentBinding
+            viewerId="org.eclipse.ui.navigator.ProjectExplorer">
+         <includes>
+            <contentExtension
+                  pattern="org.tizen.common.externals.navigatorContent">
+            </contentExtension></includes>
+      </viewerContentBinding>
+   </extension>
+   <extension
+         point="org.eclipse.ui.propertyPages">
+      <page
+            class="zipeditor.ZipNodePropertyPage"
+            id="zipeditor.ZipNodePropertyPage"
+            name="%page.name.0"
+            objectClass="zipeditor.model.ZipNode"/>
+      <page
+            class="zipeditor.TarNodePropertyPage"
+            id="zipeditor.TarNodePropertyPage"
+            name="%page.name.1"
+            objectClass="zipeditor.model.TarNode"/>
+   </extension>
+   <extension
+         point="org.eclipse.ui.commands">
+      <command
+            categoryId="org.eclipse.ui.category.edit"
+            id="zipeditor.command.selectPattern"
+            name="%command.name">
+      </command>
+      <command
+            categoryId="org.eclipse.ui.category.edit"
+            id="zipeditor.command.reverseSelection"
+            name="%command.name.0">
+      </command>
+   </extension>
+   <extension
+         point="org.eclipse.ui.bindings">
+      <key
+            commandId="zipeditor.command.selectPattern"
+            contextId="org.eclipse.ui.contexts.dialogAndWindow"
+            schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+            sequence="M1+M2++">
+      </key>
+      <key
+            commandId="zipeditor.command.reverseSelection"
+            contextId="org.eclipse.ui.contexts.dialogAndWindow"
+            schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+            sequence="M1+M2+*">
+      </key>
+   </extension>
+</plugin>
index 6201817..c656887 100644 (file)
@@ -29,17 +29,21 @@ package org.tizen.common.externals;
 import org.eclipse.ui.plugin.AbstractUIPlugin;\r
 import org.osgi.framework.BundleContext;\r
 \r
+import zipeditor.ZipEditorPlugin;\r
+\r
 /**\r
  * The activator class controls the plug-in life cycle\r
  */\r
 public class ExternalsPlugin extends AbstractUIPlugin {\r
 \r
        // The plug-in ID\r
-       public static final String PLUGIN_ID = "org.tizen.common.extras"; //$NON-NLS-1$\r
+       public static final String PLUGIN_ID = "org.tizen.common.externals"; //$NON-NLS-1$\r
 \r
        // The shared instance\r
        private static ExternalsPlugin plugin;\r
        \r
+       private static ZipEditorPlugin zipEditorPlugin;\r
+       \r
        /**\r
         * The constructor\r
         */\r
@@ -53,6 +57,8 @@ public class ExternalsPlugin extends AbstractUIPlugin {
        public void start(BundleContext context) throws Exception {\r
                super.start(context);\r
                plugin = this;\r
+               zipEditorPlugin = ZipEditorPlugin.getDefault();\r
+               zipEditorPlugin.start(context);\r
        }\r
 \r
        /*\r
@@ -62,6 +68,8 @@ public class ExternalsPlugin extends AbstractUIPlugin {
        public void stop(BundleContext context) throws Exception {\r
                plugin = null;\r
                super.stop(context);\r
+               zipEditorPlugin.stop(context);\r
+               zipEditorPlugin = null;\r
        }\r
 \r
        /**\r
diff --git a/org.tizen.common.externals/src/org/tizen/common/externals/navigatorContent/PackageActionProvider.java b/org.tizen.common.externals/src/org/tizen/common/externals/navigatorContent/PackageActionProvider.java
new file mode 100644 (file)
index 0000000..faa78c9
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Common
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * Kangho Kim <kh5325.kim@samsung.com>
+ * Gun Kim <gune.kim@samsung.com>
+ * 
+ * Licensed 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.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.common.externals.navigatorContent;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.ui.navigator.CommonActionProvider;
+import org.eclipse.ui.navigator.ICommonActionExtensionSite;
+import org.eclipse.ui.navigator.ICommonViewerSite;
+import org.eclipse.ui.navigator.ICommonViewerWorkbenchSite;
+
+public class PackageActionProvider extends CommonActionProvider {
+    Action openAction;
+    
+    @Override
+    public void init(ICommonActionExtensionSite aSite) {
+        super.init(aSite);
+        ICommonViewerSite viewSite = aSite.getViewSite();
+        if (viewSite instanceof ICommonViewerWorkbenchSite) {
+            ICommonViewerWorkbenchSite workbenchSite = (ICommonViewerWorkbenchSite) viewSite;
+            openAction = new OpenAction(aSite.getStructuredViewer(), workbenchSite.getSelectionProvider());
+        }
+    }
+    
+    class OpenAction extends Action {
+        private StructuredViewer viewer;
+        private ISelectionProvider provider; 
+
+        public OpenAction(StructuredViewer viewer, ISelectionProvider selectionProvider) {
+            this.viewer = viewer;
+            provider = selectionProvider;
+        }
+
+        public boolean isEnabled() {
+            ISelection selection = provider.getSelection();
+            if (!selection.isEmpty()) {
+                return true;
+            }
+            return false;
+        }
+
+        public void run() { 
+            ISelection selection = provider.getSelection();
+            if (selection != null && selection instanceof IStructuredSelection)
+                expand(((IStructuredSelection) selection).getFirstElement());
+        }
+
+        private void expand(Object target) {
+            if (target != null && (viewer instanceof TreeViewer)) {
+                TreeViewer treeViewer = (TreeViewer) viewer;
+                treeViewer.setExpandedState(target, !treeViewer.getExpandedState(target));
+            }
+        }
+    }
+
+}
diff --git a/org.tizen.common.externals/src/org/tizen/common/externals/navigatorContent/PackageContentProvider.java b/org.tizen.common.externals/src/org/tizen/common/externals/navigatorContent/PackageContentProvider.java
new file mode 100644 (file)
index 0000000..15e2261
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Common
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * Kangho Kim <kh5325.kim@samsung.com>
+ * Gun Kim <gune.kim@samsung.com>
+ * 
+ * Licensed 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.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.common.externals.navigatorContent;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+import zipeditor.ZipContentProvider;
+
+
+public class PackageContentProvider implements ITreeContentProvider {
+
+    @Override
+    public void dispose() {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public Object[] getElements(Object inputElement) {
+        return getChildren(inputElement);
+    }
+
+    @Override
+    public Object[] getChildren(Object parentElement) {
+        if (parentElement instanceof IFolder) {
+            List<IFile> children = new ArrayList<IFile>();
+            try {
+                for ( IResource child : ((IFolder) parentElement).members() ) {
+                    if ( child instanceof IFile ) {
+                        if ( ZipContentProvider.isForUs((IFile) child) ) {
+                            children.add((IFile) child);
+                        }
+                    }
+                }
+                return children.toArray();
+            } catch (CoreException e) {
+                return new Object[0];
+            }
+        }
+        
+        return new Object[0];
+    }
+
+    @Override
+    public Object getParent(Object element) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean hasChildren(Object element) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+}
diff --git a/org.tizen.common.externals/src/org/tizen/common/externals/navigatorContent/PackageLabelProvider.java b/org.tizen.common.externals/src/org/tizen/common/externals/navigatorContent/PackageLabelProvider.java
new file mode 100644 (file)
index 0000000..88a4ef4
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Common
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: 
+ * Kangho Kim <kh5325.kim@samsung.com>
+ * Gun Kim <gune.kim@samsung.com>
+ * 
+ * Licensed 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.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.common.externals.navigatorContent;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.swt.graphics.Image;
+import org.tizen.common.TizenPlatformConstants;
+
+import zipeditor.ZipContentProvider;
+import zipeditor.ZipEditorPlugin;
+
+
+public class PackageLabelProvider implements ILabelProvider {
+
+    @Override
+    public void addListener(ILabelProviderListener listener) {
+    }
+
+    @Override
+    public void dispose() {
+    }
+
+    @Override
+    public boolean isLabelProperty(Object element, String property) {
+        return false;
+    }
+
+    @Override
+    public void removeListener(ILabelProviderListener listener) {
+    }
+
+    @Override
+    public Image getImage(Object element) {
+        if ( element instanceof IFile ) {
+            IFile file = (IFile) element;
+            if ( ZipContentProvider.isForUs(file) ) {
+                if ( file.getFileExtension() == null ) {
+                    return null;
+                }
+                
+                String fileExt = file.getFileExtension().toUpperCase();
+                if ( TizenPlatformConstants.PKGTYPE_WGT.equals(fileExt) ) {
+                    return ZipEditorPlugin.getImage("icons/wgt.png");
+                }
+                else if ( TizenPlatformConstants.PKGTYPE_TPK.equals(fileExt) ) {
+                    return ZipEditorPlugin.getImage("icons/tpk.png");
+                }
+            }
+        }
+        
+        return null;
+    }
+
+    @Override
+    public String getText(Object element) {
+        return null;
+    }
+
+}
diff --git a/org.tizen.common.externals/src/zipeditor/LocalFileEditorInput.java b/org.tizen.common.externals/src/zipeditor/LocalFileEditorInput.java
new file mode 100644 (file)
index 0000000..ce04f53
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import java.io.InputStream;
+
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.ui.IPathEditorInput;
+import org.eclipse.ui.IPersistableElement;
+import org.eclipse.ui.IStorageEditorInput;
+import org.eclipse.ui.editors.text.ILocationProvider;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+public class LocalFileEditorInput implements IPathEditorInput, IStorageEditorInput, ILocationProvider {
+       private class WorkbenchAdapter implements IWorkbenchAdapter {
+               public Object[] getChildren(Object o) {
+                       return null;
+               }
+
+               public ImageDescriptor getImageDescriptor(Object object) {
+                       return null;
+               }
+
+               public String getLabel(Object o) {
+                       return ((LocalFileEditorInput)o).getName();
+               }
+
+               public Object getParent(Object o) {
+                       return null;
+               }
+       };
+
+       private class FileStorage implements IStorage {
+               private IFileStore fFileStore;
+               private IPath fFullPath;
+               
+               public FileStorage(IFileStore fileStore) {
+                       Assert.isNotNull(fileStore);
+                       Assert.isTrue(EFS.SCHEME_FILE.equals(fileStore.getFileSystem().getScheme()));
+                       fFileStore = fileStore;
+               }
+               
+               public InputStream getContents() throws CoreException {
+                       return fFileStore.openInputStream(EFS.NONE, null);
+               }
+
+               public IPath getFullPath() {
+               if (fFullPath == null)
+                       fFullPath = new Path(fFileStore.toURI().getPath());
+               return fFullPath;
+               }
+
+               public String getName() {
+                       return fFileStore.getName();
+               }
+
+               public boolean isReadOnly() {
+                       return fFileStore.fetchInfo().getAttribute(EFS.ATTRIBUTE_READ_ONLY);
+               }
+
+               public Object getAdapter(Class adapter) {
+                       return null;
+               }
+       };
+
+       private IFileStore fFileStore;
+       private WorkbenchAdapter fWorkbenchAdapter = new WorkbenchAdapter();
+       private IStorage fStorage;
+       private IPath fPath;
+       
+       public LocalFileEditorInput(IFileStore fileStore) {
+               Assert.isNotNull(fileStore);
+               Assert.isTrue(EFS.SCHEME_FILE.equals(fileStore.getFileSystem().getScheme()));
+               fFileStore = fileStore;
+               fWorkbenchAdapter = new WorkbenchAdapter();
+       }
+
+       public boolean exists() {
+               return fFileStore.fetchInfo().exists();
+       }
+
+       public ImageDescriptor getImageDescriptor() {
+               return null;
+       }
+
+       public String getName() {
+               return fFileStore.getName();
+       }
+
+       public IPersistableElement getPersistable() {
+               return null;
+       }
+
+       public String getToolTipText() {
+               return fFileStore.toString();
+       }
+
+       public Object getAdapter(Class adapter) {
+               if (ILocationProvider.class.equals(adapter))
+                       return this;
+               if (IWorkbenchAdapter.class.equals(adapter))
+                       return fWorkbenchAdapter;
+               return Platform.getAdapterManager().getAdapter(this, adapter);
+       }
+
+       public IPath getPath(Object element) {
+               if (element instanceof LocalFileEditorInput)
+                       return ((LocalFileEditorInput)element).getPath();
+               
+               return null;
+       }
+
+    public IPath getPath() {
+       if (fPath == null)
+               fPath = new Path(fFileStore.toURI().getPath());
+       return fPath;
+    }
+
+       public boolean equals(Object o) {
+               if (o == this)
+                       return true;
+
+               if (o instanceof LocalFileEditorInput) {
+                       LocalFileEditorInput input = (LocalFileEditorInput) o;
+                       return fFileStore.equals(input.fFileStore);
+               }
+
+        if (o instanceof IPathEditorInput) {
+            IPathEditorInput input= (IPathEditorInput)o;
+            return getPath().equals(input.getPath());
+        }
+               return false;
+       }
+
+       public int hashCode() {
+               return fFileStore.hashCode();
+       }
+
+       public IStorage getStorage() throws CoreException {
+               if (fStorage == null)
+                       fStorage = new FileStorage(fFileStore);
+               return fStorage;
+       }
+
+}
diff --git a/org.tizen.common.externals/src/zipeditor/Messages.java b/org.tizen.common.externals/src/zipeditor/Messages.java
new file mode 100644 (file)
index 0000000..58da50a
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+       private static final String BUNDLE_NAME = "zipeditor.messages"; //$NON-NLS-1$
+
+       private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+                       .getBundle(BUNDLE_NAME);
+
+       private Messages() {
+       }
+
+       public static String getString(String key) {
+               try {
+                       return RESOURCE_BUNDLE.getString(key);
+               } catch (MissingResourceException e) {
+                       return '!' + key + '!';
+               }
+       }
+
+       public static String getFormattedString(String key, Object argument) {
+               try {
+                       String pattern = RESOURCE_BUNDLE.getString(key);
+                       return MessageFormat.format(pattern, argument instanceof Object[] ? (Object[]) argument : new Object[] { argument });
+               } catch (MissingResourceException e) {
+                       return '!' + key + '!';
+               }
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/MultiElementPropertyPage.java b/org.tizen.common.externals/src/zipeditor/MultiElementPropertyPage.java
new file mode 100644 (file)
index 0000000..8150b41
--- /dev/null
@@ -0,0 +1,98 @@
+package zipeditor;
+
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.PropertyPage;
+
+public abstract class MultiElementPropertyPage extends PropertyPage {
+       protected interface PropertyAccessor {
+               Object getPropertyValue(Object object);
+       };
+
+       protected class MultiplePropertyAccessor implements PropertyAccessor {
+               private PropertyDescriptor[] fDescriptors;
+               private String fPropertyName;
+
+               public MultiplePropertyAccessor(Class clazz) {
+                       try {
+                               fDescriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors();
+                       } catch (Exception e) {
+                               ZipEditorPlugin.log(e);
+                       }
+               }
+
+               public Object getPropertyValue(Object object) {
+                       for (int i = 0; i < fDescriptors.length; i++) {
+                               if (!fDescriptors[i].getName().equals(fPropertyName))
+                                       continue;
+                               try {
+                                       return fDescriptors[i].getReadMethod().invoke(object, null);
+                               } catch (Exception e) {
+                                       ZipEditorPlugin.log(e);
+                               }
+                       }
+                       return null;
+               }
+
+               public PropertyAccessor getAccessor(String property) {
+                       fPropertyName = property;
+                       return this;
+               }
+               
+       };
+
+       private IAdaptable[] fElements;
+
+       protected String nonEqualStringLabel = Messages.getString("MultiElementPropertyPage.0"); //$NON-NLS-1$
+
+       public void setElements(IAdaptable[] elements) {
+               fElements = elements;
+       }
+       
+       public void setElement(IAdaptable element) {
+               if (element != null)
+                       fElements = new IAdaptable[] { element };
+       }
+       
+       public IAdaptable[] getElements() {
+               return fElements;
+       }
+
+       protected void setFieldText(Text field, PropertyAccessor accessor) {
+               setFieldText(field, accessor, false);
+       }
+
+       protected void setFieldText(Text field, PropertyAccessor accessor, boolean summate) {
+               Object[] values = new Object[fElements.length];
+               Number sum = null;
+               for (int i = 0; i < fElements.length; i++) {
+                       values[i] = accessor.getPropertyValue(fElements[i]);
+                       if (summate && values[i] instanceof Number) {
+                               sum = new Long(((Number) values[i]).longValue() + (sum != null ? sum.longValue() : 0));
+                       }
+               }
+               final Object unequalValue = new Object();
+               Object singularValue = values.length > 0 ? values[0] : null;
+               for (int i = 1; i < values.length; i++) {
+                       singularValue = values[i];
+                       if (values[i] == values[i - 1] || values[i] != null && values[i].equals(values[i - 1]))
+                               continue;
+                       singularValue = unequalValue;
+                       break;
+               }
+               if (sum != null) {
+                       field.setText(formatLong(sum.longValue()));
+               } else if (singularValue == unequalValue) {
+                       field.setText(nonEqualStringLabel);
+               } else if (singularValue != null) {
+                       field.setText(singularValue.toString());
+               }
+       }
+
+       protected String formatLong(long value) {
+               return ZipLabelProvider.formatLong(value);
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/MultiPreferenceDialog.java b/org.tizen.common.externals/src/zipeditor/MultiPreferenceDialog.java
new file mode 100644 (file)
index 0000000..d305b9d
--- /dev/null
@@ -0,0 +1,68 @@
+package zipeditor;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.preference.PreferenceDialog;
+import org.eclipse.jface.preference.PreferenceManager;
+import org.eclipse.jface.preference.PreferenceNode;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+public class MultiPreferenceDialog extends PreferenceDialog {
+       private IAdaptable[] fElements;
+       private MultiElementPropertyPage fPropertyPage;
+
+       public MultiPreferenceDialog(Shell parentShell, PreferenceManager manager,
+                       IAdaptable[] elements) {
+               super(parentShell, manager);
+               fElements = elements;
+       }
+       
+       protected void configureShell(Shell newShell) {
+               super.configureShell(newShell);
+               newShell.setText(createText());
+               
+               selectPropertyPage();
+       }
+
+       private void selectPropertyPage() {
+        IExtension[] extensions = Platform.getExtensionRegistry().getExtensionPoint("org.eclipse.ui.propertyPages").getExtensions(); //$NON-NLS-1$
+        for (int i = 0; i < extensions.length; i++) {
+               if (!extensions[i].getContributor().getName().equals(ZipEditorPlugin.PLUGIN_ID))
+                       continue;
+               IConfigurationElement[] elements = extensions[i].getConfigurationElements();
+               for (int j = 0; j < elements.length; j++) {
+                               String objectClass = elements[j].getAttribute("objectClass"); //$NON-NLS-1$
+                               if (objectClass == null)
+                                       continue;
+                               try {
+                                       Class clazz = Platform.getBundle(elements[j].getContributor().getName()).loadClass(objectClass);
+                                       if (fElements != null && fElements.length > 0 && fElements[0].getClass().isAssignableFrom(clazz)) {
+                                               fPropertyPage = (MultiElementPropertyPage) elements[j].createExecutableExtension("class"); //$NON-NLS-1$
+                                               fPropertyPage.setElements(fElements);
+                                               fPropertyPage.setTitle(elements[j].getAttribute("name")); //$NON-NLS-1$
+                                               getPreferenceManager().addToRoot(new PreferenceNode(new String(), fPropertyPage));
+                                               break;
+                                       }
+                               } catch (Exception e) {
+                                       ZipEditorPlugin.log(e);
+                                       continue;
+                               }
+               }
+               }
+       }
+
+       private String createText() {
+               if (fElements != null) {
+                       if (fElements.length == 1) {
+                               String s = ((IWorkbenchAdapter) fElements[0].getAdapter(IWorkbenchAdapter.class)).getLabel(fElements[0]);
+                               return Messages.getFormattedString("MultiPreferenceDialog.0", s); //$NON-NLS-1$
+                       } else {
+                               return Messages.getFormattedString("MultiPreferenceDialog.1", new Integer(fElements.length)); //$NON-NLS-1$
+                       }
+               }
+               return Messages.getFormattedString("MultiPreferenceDialog.0", null); //$NON-NLS-1$
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/NodePropertyPage.java b/org.tizen.common.externals/src/zipeditor/NodePropertyPage.java
new file mode 100644 (file)
index 0000000..3f7c58e
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import java.text.ParseException;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+import zipeditor.model.Node;
+import zipeditor.model.NodeProperty;
+
+public abstract class NodePropertyPage extends MultiElementPropertyPage {
+       protected abstract class NodePropertyAccessor implements PropertyAccessor {
+               public Object getPropertyValue(Object object) {
+                       Node node = (Node) object;
+                       if (node.isFolder()) {
+                               Node[] children = node.getChildren();
+                               Object aggregate = getSinglePropertyValue(node);
+                               for (int i = 0; i < children.length; i++) {
+                                       aggregate = aggregatePropertyValues(getPropertyValue(children[i]), aggregate);
+                               }
+                               return aggregate;
+                       } else {
+                               return getSinglePropertyValue(node);
+                       }
+               }
+               
+               protected Object aggregatePropertyValues(Object value1, Object value2) {
+                       if (value1 instanceof Number && value2 instanceof Number)
+                               return new Long(((Number) value1).longValue() + ((Number) value2).longValue());
+                       return value1;
+               }
+
+               protected abstract Object getSinglePropertyValue(Node node);
+       }
+
+       private Text fName;
+       private Text fPath;
+       private Text fType;
+       private Text fDate;
+       private Text fSize;
+       
+       protected Control createPropertiesSection(Composite parent) {
+               Group control = new Group(parent, SWT.NONE);
+               control.setLayout(new GridLayout(2, false));
+
+               MultiplePropertyAccessor accessor = new MultiplePropertyAccessor(Node.class);
+
+               createLabel(control, NodeProperty.PNAME.toString(), 1);
+               fName = createText(control, 30, 1, true);
+               setFieldText(fName, accessor.getAccessor("name")); //$NON-NLS-1$
+               createLabel(control, NodeProperty.PTYPE.toString(), 1);
+               fType = createText(control, 30, 1, false);
+
+               setFieldText(fType, new PropertyAccessor() {
+                       public Object getPropertyValue(Object object) {
+                               return ZipLabelProvider.getTypeLabel((Node) object);
+                       }
+               });
+               createLabel(control, NodeProperty.PPATH.toString(), 1);
+               fPath = createText(control, 30, 1, false);
+               setFieldText(fPath, accessor.getAccessor("path")); //$NON-NLS-1$
+               
+               createLabel(control, NodeProperty.PDATE.toString(), 1);
+               fDate = createText(control, 30, 1, true);
+               setFieldText(fDate, new PropertyAccessor() {
+                       public Object getPropertyValue(Object object) {
+                               return formatDate(((Node) object).getTime());
+                       }
+               });
+               createLabel(control, NodeProperty.PSIZE.toString(), 1);
+               fSize = createText(control, 30, 1, false);
+               setFieldText(fSize, new NodePropertyAccessor() {
+                       public Object getSinglePropertyValue(Node node) {
+                               return new Long(node.getSize());
+                       }
+               }, true);
+
+               return control;
+       }
+       
+       protected Node[] getNodes() {
+               IAdaptable[] elements = getElements();
+               Node[] nodes = new Node[elements.length];
+               for (int i = 0; i < nodes.length; i++) {
+                       nodes[i] = (Node) elements[i].getAdapter(Node.class);
+               }
+               return nodes;
+       }
+
+       protected String formatDate(long time) {
+               return ZipLabelProvider.formatDate(time);
+       }
+
+       protected long parseDate(String string) throws ParseException {
+               return ZipLabelProvider.DATE_FORMAT.parse(string).getTime();
+       }
+
+       protected Label createLabel(Composite parent, String text, int hspan) {
+               Label label = new Label(parent, SWT.LEFT);
+               label.setText(text);
+               GridData data = new GridData(GridData.FILL_HORIZONTAL);
+               data.horizontalSpan = hspan;
+               label.setLayoutData(data);
+               return label;
+       }
+
+       protected Text createText(Composite parent, int width, int hspan, boolean editable) {
+               Text text = new Text(parent, SWT.BORDER);
+               GridData data = new GridData(GridData.FILL_HORIZONTAL);
+               data.horizontalSpan = hspan;
+               data.widthHint = convertWidthInCharsToPixels(width);
+               text.setLayoutData(data);
+               text.setEditable(editable);
+               return text;
+       }
+       
+       public boolean performOk() {
+               Node[] nodes = getNodes();
+               String name = fName.getText();
+               Long time = null;
+               String dateText = fDate.getText();
+               if (dateText.trim().length() > 0 && !nonEqualStringLabel.equals(dateText)) {
+                       try {
+                               time = new Long(parseDate(dateText));
+                               setErrorMessage(null);
+                       } catch (ParseException e) {
+                               String pattern = ZipLabelProvider.DATE_FORMAT.format(new Long(System.currentTimeMillis()));
+                               setErrorMessage(Messages.getFormattedString("NodePropertyPage.0", new Object[] { dateText, pattern })); //$NON-NLS-1$
+                               return false;
+                       }
+               }
+               for (int i = 0; i < nodes.length; i++) {
+                       if (!nonEqualStringLabel.equals(name))
+                               nodes[i].setName(name);
+                       if (time != null)
+                               nodes[i].setTime(time.longValue());
+               }
+               return true;
+       }
+
+}
\ No newline at end of file
diff --git a/org.tizen.common.externals/src/zipeditor/PreferenceConstants.java b/org.tizen.common.externals/src/zipeditor/PreferenceConstants.java
new file mode 100644 (file)
index 0000000..29066d5
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+public class PreferenceConstants {
+
+       public final static String VIEW_MODE = "VIEW_MODE"; //$NON-NLS-1$
+
+       public final static String SORT_BY = "SORT_BY"; //$NON-NLS-1$
+
+       public final static String SORT_COLUMN_WIDTH = "SORT_COLUMN_WIDTH"; //$NON-NLS-1$
+
+       public final static String SORT_DIRECTION = "SORT_DIRECTION"; //$NON-NLS-1$
+
+       public final static String VISIBLE_COLUMNS = "VISIBLE_COLUMNS"; //$NON-NLS-1$
+
+       public final static String COLUMNS_SEPARATOR = ","; //$NON-NLS-1$
+
+       public final static String SORT_ENABLED = "SORT_ENABLED"; //$NON-NLS-1$
+
+       public final static String EXTERNAL_EDITORS = "EXTERNAL_EDITORS"; //$NON-NLS-1$
+       
+       public final static String PREFIX_EDITOR = "editor"; //$NON-NLS-1$
+
+       public final static String PREFIX_OUTLINE = "outline"; //$NON-NLS-1$
+
+       public final static String PREFIX_NAVIGATOR = "commonNavigator"; //$NON-NLS-1$
+
+       public final static int VIEW_MODE_TREE = 0x02;
+       
+       public final static int VIEW_MODE_FOLDERS_VISIBLE = 0x04;
+
+       public final static int VIEW_MODE_FOLDERS_ONE_LAYER = 0x08;
+
+       public final static String RECENTLY_USED_EDITORS = "recentlyUsedEditors"; //$NON-NLS-1$
+       
+       public final static String RECENTLY_USED_SEPARATOR = ","; //$NON-NLS-1$
+
+       public final static String STORE_FOLDERS_IN_ARCHIVES = "storeFoldersInArchives"; //$NON-NLS-1$
+
+       private PreferenceConstants() {
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/PreferenceInitializer.java b/org.tizen.common.externals/src/zipeditor/PreferenceInitializer.java
new file mode 100644 (file)
index 0000000..d7aa513
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import java.lang.reflect.Array;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+
+import zipeditor.model.NodeProperty;
+
+public class PreferenceInitializer extends AbstractPreferenceInitializer {
+
+       public PreferenceInitializer() {
+       }
+
+       public void initializeDefaultPreferences() {
+               IPreferenceStore store = ZipEditorPlugin.getDefault().getPreferenceStore();
+
+               store.setDefault(PreferenceConstants.PREFIX_OUTLINE + PreferenceConstants.VIEW_MODE, PreferenceConstants.VIEW_MODE_TREE);
+               store.setDefault(PreferenceConstants.PREFIX_OUTLINE + PreferenceConstants.SORT_ENABLED, true);
+               store.setDefault(PreferenceConstants.PREFIX_NAVIGATOR + PreferenceConstants.VIEW_MODE, PreferenceConstants.VIEW_MODE_TREE);
+               store.setDefault(PreferenceConstants.PREFIX_NAVIGATOR + PreferenceConstants.SORT_ENABLED, true);
+               store.setDefault(PreferenceConstants.PREFIX_EDITOR + PreferenceConstants.VIEW_MODE, PreferenceConstants.VIEW_MODE_FOLDERS_ONE_LAYER);
+               store.setDefault(PreferenceConstants.PREFIX_EDITOR + PreferenceConstants.SORT_ENABLED, true);
+               store.setDefault(PreferenceConstants.SORT_BY, NodeProperty.NAME);
+               store.setDefault(PreferenceConstants.SORT_DIRECTION, SWT.UP);
+               store.setDefault(PreferenceConstants.VISIBLE_COLUMNS, join(new Object[] {
+                               new Integer(NodeProperty.NAME),
+                               new Integer(NodeProperty.TYPE),
+                               new Integer(NodeProperty.DATE),
+                               new Integer(NodeProperty.SIZE),
+                               new Integer(NodeProperty.PATH),
+               }, PreferenceConstants.COLUMNS_SEPARATOR));
+       }
+
+       public final static String join(Object array, String separator) {
+               StringBuffer sb = new StringBuffer();
+               for (int i = 0, n = Array.getLength(array); i < n; i++) {
+                       if (sb.length() > 0)
+                               sb.append(separator);
+                       Object object = Array.get(array, i);
+                       if (object != null)
+                               sb.append(object);
+               }
+               return sb.toString();
+       }
+
+       public final static Object split(String string, String separator, Class elementType) {
+               StringTokenizer st = new StringTokenizer(string, separator);
+               int size = st.countTokens();
+               Object result = Array.newInstance(elementType, size);
+               for (int i = 0; i < size; i++) {
+                       try {
+                               Array.set(result, i, valueFromString(st.nextToken(), elementType));
+                       } catch (Exception e) {
+                               ZipEditorPlugin.log(e);
+                       }
+               }
+               return result;
+       }
+
+       private static Object valueFromString(String string, Class type) throws Exception {
+               if (type == int.class)
+                       type = Integer.class;
+               else if (type == short.class)
+                       type = Short.class;
+               else if (type == long.class)
+                       type = Long.class;
+               else if (type == double.class)
+                       type = Double.class;
+               else if (type == float.class)
+                       type = Float.class;
+               else if (type == char.class)
+                       type = Character.class;
+               else if (type == boolean.class)
+                       type = Boolean.class;
+               return type.getConstructor(new Class[] { String.class }).newInstance(new Object[] { string });
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/TableFrame.java b/org.tizen.common.externals/src/zipeditor/TableFrame.java
new file mode 100644 (file)
index 0000000..accb682
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.views.framelist.Frame;
+
+import zipeditor.model.Node;
+import zipeditor.model.ZipModel;
+
+public class TableFrame extends Frame {
+       private static final String TAG_SELECTION = "selection"; //$NON-NLS-1$
+       private static final String TAG_ELEMENT = "element"; //$NON-NLS-1$
+       private static final String TAG_FRAME_INPUT = "frameInput"; //$NON-NLS-1$
+       private static final String TAG_PATH = "nodePath"; //$NON-NLS-1$
+
+       private TableViewer fViewer;
+       private Object fInput;
+       private ISelection fSelection;
+
+       public TableFrame(TableViewer viewer) {
+               fViewer = viewer;
+       }
+
+       public TableFrame(TableViewer viewer, Object input) {
+               this(viewer);
+               setInput(input);
+               ILabelProvider provider = (ILabelProvider) viewer.getLabelProvider();
+               String name = provider.getText(input);
+               if (name == null) {
+                       name = "";//$NON-NLS-1$
+               }
+               setName(name);
+               setToolTipText(name);
+       }
+
+       public Object getInput() {
+               return fInput;
+       }
+
+       public ISelection getSelection() {
+               return fSelection;
+       }
+
+       public TableViewer getViewer() {
+               return fViewer;
+       }
+
+       public void restoreState(IMemento memento, ZipModel model) {
+               IMemento inputMem = memento.getChild(TAG_FRAME_INPUT);
+               String inputPath = inputMem != null ? inputMem.getString(TAG_PATH) : null;
+               if (inputPath != null)
+                       fInput = model.findNode(inputPath);
+
+               IMemento selectionMem = memento.getChild(TAG_SELECTION);
+               if (selectionMem != null) {
+                       IMemento[] elements = selectionMem.getChildren(TAG_ELEMENT);
+                       List selection = new ArrayList();
+                       for (int i = 0; i < elements.length; i++) {
+                               String nodePath = elements[i].getString(TAG_PATH);
+                               if (nodePath == null)
+                                       continue;
+                               Node node = model.findNode(nodePath);
+                               if (node != null)
+                                       selection.add(node);
+                       }
+                       fSelection = new StructuredSelection(selection);
+               } else {
+                       fSelection = StructuredSelection.EMPTY;
+               }
+       }
+
+       private void saveNode(Node node, IMemento memento, String childTag) {
+               IMemento childMem = memento.createChild(childTag);
+               childMem.putString(TAG_PATH, node.getFullPath());
+       }
+
+       public void saveState(IMemento memento) {
+               if (fInput instanceof Node)
+                       saveNode((Node) fInput, memento, TAG_FRAME_INPUT);
+
+               if (fSelection instanceof IStructuredSelection) {
+                       Object[] elements = ((IStructuredSelection) fSelection).toArray();
+                       if (elements.length > 0) {
+                               IMemento selectionMem = memento.createChild(TAG_SELECTION);
+                               for (int i = 0; i < elements.length; i++) {
+                                       if (elements[i] instanceof Node)
+                                               saveNode((Node) elements[i], selectionMem, TAG_ELEMENT);
+                               }
+                       }
+               }
+       }
+
+       public void setInput(Object input) {
+               fInput = input;
+       }
+
+       public void setSelection(ISelection selection) {
+               fSelection = selection;
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/TableViewerFrameSource.java b/org.tizen.common.externals/src/zipeditor/TableViewerFrameSource.java
new file mode 100644 (file)
index 0000000..46c9b2f
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.ui.views.framelist.Frame;
+import org.eclipse.ui.views.framelist.FrameList;
+import org.eclipse.ui.views.framelist.IFrameSource;
+
+public class TableViewerFrameSource implements IFrameSource {
+       private TableViewer fViewer;
+
+       public TableViewerFrameSource(TableViewer viewer) {
+               fViewer = viewer;
+       }
+
+       public void connectTo(FrameList frameList) {
+               frameList.addPropertyChangeListener(new IPropertyChangeListener() {
+                       public void propertyChange(PropertyChangeEvent event) {
+                               TableViewerFrameSource.this.handlePropertyChange(event);
+                       }
+               });
+       }
+
+       protected TableFrame createFrame(Object input) {
+               return new TableFrame(fViewer, input);
+       }
+
+       protected void frameChanged(TableFrame frame) {
+               fViewer.getControl().setRedraw(false);
+               fViewer.setInput(frame.getInput());
+               fViewer.setSelection(frame.getSelection(), true);
+               fViewer.getControl().setRedraw(true);
+       }
+
+       protected Frame getCurrentFrame(int flags) {
+               Object input = fViewer.getInput();
+               TableFrame frame = createFrame(input);
+               if ((flags & IFrameSource.FULL_CONTEXT) != 0) {
+                       frame.setSelection(fViewer.getSelection());
+               }
+               return frame;
+       }
+
+       public Frame getFrame(int whichFrame, int flags) {
+               switch (whichFrame) {
+               case IFrameSource.CURRENT_FRAME:
+                       return getCurrentFrame(flags);
+               case IFrameSource.PARENT_FRAME:
+                       return getParentFrame(flags);
+               case IFrameSource.SELECTION_FRAME:
+                       return getSelectionFrame(flags);
+               default:
+                       return null;
+               }
+       }
+
+       protected Frame getParentFrame(int flags) {
+               Object input = fViewer.getInput();
+               ITreeContentProvider provider = (ITreeContentProvider) fViewer
+                               .getContentProvider();
+               Object parent = provider.getParent(input);
+               if (parent == null) {
+                       return null;
+               } else {
+                       TableFrame frame = createFrame(parent);
+                       if ((flags & IFrameSource.FULL_CONTEXT) != 0) {
+                               frame.setSelection(fViewer.getSelection());
+                       }
+                       return frame;
+               }
+       }
+
+       protected Frame getSelectionFrame(int flags) {
+               IStructuredSelection sel = (IStructuredSelection) fViewer
+                               .getSelection();
+               if (sel.size() == 1) {
+                       Object o = sel.getFirstElement();
+                       TableFrame frame = createFrame(o);
+                       if ((flags & IFrameSource.FULL_CONTEXT) != 0) {
+                               frame.setSelection(fViewer.getSelection());
+                       }
+                       return frame;
+               }
+               return null;
+       }
+
+       public TableViewer getViewer() {
+               return fViewer;
+       }
+
+       protected void handlePropertyChange(PropertyChangeEvent event) {
+               if (FrameList.P_CURRENT_FRAME.equals(event.getProperty())) {
+                       frameChanged((TableFrame) event.getNewValue());
+               }
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/TarNodePropertyPage.java b/org.tizen.common.externals/src/zipeditor/TarNodePropertyPage.java
new file mode 100644 (file)
index 0000000..c71966b
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbenchPropertyPage;
+
+import zipeditor.model.Node;
+import zipeditor.model.TarNode;
+import zipeditor.model.TarNodeProperty;
+
+public class TarNodePropertyPage extends NodePropertyPage implements IWorkbenchPropertyPage {
+       private Text fGroupId;
+       private Text fGroupName;
+       private Text fUserId;
+       private Text fUserName;
+       
+       protected Control createContents(Composite parent) {
+               Composite control = (Composite) createPropertiesSection(parent);
+
+               MultiplePropertyAccessor accessor = new MultiplePropertyAccessor(TarNode.class);
+               createLabel(control, TarNodeProperty.PGROUP_ID.toString(), 1);
+               fGroupId = createText(control, 30, 1, true);
+               setFieldText(fGroupId, accessor.getAccessor("groupId")); //$NON-NLS-1$
+               createLabel(control, TarNodeProperty.PGROUP_NAME.toString(), 1);
+               fGroupName = createText(control, 30, 1, true);
+               setFieldText(fGroupName, accessor.getAccessor("groupName")); //$NON-NLS-1$
+               createLabel(control, TarNodeProperty.PUSER_ID.toString(), 1);
+               fUserId = createText(control, 30, 1, true);
+               setFieldText(fUserId, accessor.getAccessor("userId")); //$NON-NLS-1$
+               createLabel(control, TarNodeProperty.PUSER_NAME.toString(), 1);
+               fUserName = createText(control, 30, 1, true);
+               setFieldText(fUserName, accessor.getAccessor("userName")); //$NON-NLS-1$
+               
+               applyDialogFont(control);
+               return control;
+       }
+       
+       public boolean performOk() {
+               boolean ok = super.performOk();
+               if (!ok)
+                       return false;
+               Node[] nodes = getNodes();
+               Integer groupId = null;
+               Integer userId = null;
+               if (!nonEqualStringLabel.equals(fGroupId)) {
+                       try {
+                               groupId = new Integer(fGroupId.getText());
+                               setErrorMessage(null);
+                       } catch (Exception e) {
+                               setErrorMessage(Messages.getString("TarNodePropertyPage.0")); //$NON-NLS-1$
+                               return false;
+                       }
+               }
+               try {
+                       userId = new Integer(fUserId.getText());
+                       setErrorMessage(null);
+               } catch (Exception e) {
+                       setErrorMessage(Messages.getString("TarNodePropertyPage.1")); //$NON-NLS-1$
+                       return false;
+               }
+               for (int i = 0; i < nodes.length; i++) {
+                       if (groupId != null)
+                               ((TarNode) nodes[i]).setGroupId(groupId.intValue());
+                       if (!nonEqualStringLabel.equals(fGroupName.getText()))
+                               ((TarNode) nodes[i]).setGroupName(fGroupName.getText());
+                       if (userId != null)
+                               ((TarNode) nodes[i]).setUserId(userId.intValue());
+                       if (!nonEqualStringLabel.equals(fUserName.getText()))
+                               ((TarNode) nodes[i]).setUserName(fUserName.getText());
+               }
+               return true;
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/Utils.java b/org.tizen.common.externals/src/zipeditor/Utils.java
new file mode 100644 (file)
index 0000000..50a91c9
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorRegistry;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.ElementListSelectionDialog;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.ide.FileStoreEditorInput;
+import org.eclipse.ui.part.FileEditorInput;
+
+import zipeditor.model.Node;
+import zipeditor.operations.ExtractOperation;
+import zipeditor.operations.OpenFileOperation;
+
+public class Utils {
+       private static class ExtractAndOpenJob extends Job {
+               private Node[] fNodes;
+
+               public ExtractAndOpenJob(Node[] nodes) {
+                       super(Messages.getString("Utils.0")); //$NON-NLS-1$
+                       fNodes = nodes;
+               }
+               
+               protected IStatus run(IProgressMonitor monitor) {
+                       monitor.beginTask(Messages.getString("Utils.1"), fNodes.length); //$NON-NLS-1$
+                       try {
+                               internalOpenFilesFromNodes(fNodes, monitor);
+                       } finally {
+                               monitor.done();
+                       }
+                       return Status.OK_STATUS;
+               }
+       };
+
+       public static int computeTotalNumber(Node[] nodes, IProgressMonitor monitor) {
+               int result = 0;
+               for (int i = 0; i < nodes.length; i++) {
+                       if (monitor.isCanceled())
+                               break;
+                       if (nodes[i].isFolder())
+                               result += computeTotalNumber(nodes[i].getChildren(), monitor);
+                       else
+                               result++;
+               }
+               return result;
+       }
+
+       public static int computeTotalNumber(File[] files, IProgressMonitor monitor) {
+               if (files == null)
+                       return 0;
+               int result = 0;
+               for (int i = 0; i < files.length; i++) {
+                       if (monitor.isCanceled())
+                               break;
+                       if (files[i].isDirectory())
+                               result += computeTotalNumber(files[i].listFiles(), monitor);
+                       else
+                               result++;
+               }
+               return result;
+       }
+
+       public static boolean isUIThread() {
+               return Display.getCurrent() != null;
+       }
+       
+       public static IFileStore getFileStore(File file) {
+               IFileStore fileStore = EFS.getLocalFileSystem().getStore(new Path(file.getParentFile().getAbsolutePath()));
+               return fileStore.getChild(file.getName());
+       }
+       
+       public static void openFilesFromNodes(Node[] nodes) {
+               if (nodes == null || nodes.length == 0)
+                       return;
+               ExtractAndOpenJob job = new ExtractAndOpenJob(nodes);
+               job.schedule();
+       }
+
+       private static void internalOpenFilesFromNodes(Node[] nodes, IProgressMonitor monitor) {
+               File tmpDir = nodes[0].getModel().getTempDir();
+               ExtractOperation extractOperation = new ExtractOperation();
+               OpenFileOperation openFileOperation = new OpenFileOperation();
+               for (int i = 0; i < nodes.length; i++) {
+                       Node node = nodes[i];
+                       monitor.subTask(node.getName());
+                       File file = extractOperation.extract(node, tmpDir, true, monitor);
+                       openFileOperation.execute(file);
+                       ZipEditorPlugin.getDefault().addFileMonitor(file, node);
+                       monitor.worked(1);
+               }
+       }
+       
+       public static IEditorInput createEditorInput(IFileStore fileStore) {
+               IFile workspaceFile = getWorkspaceFile(fileStore);
+               if (workspaceFile != null)
+                       return new FileEditorInput(workspaceFile);
+               try {
+                       return new FileStoreEditorInput(fileStore);
+               } catch (Throwable ignore) { // not available
+                       return new LocalFileEditorInput(fileStore);
+               }
+       }
+       
+       public static String getEditorId(IFileStore file) {
+               IWorkbench workbench = PlatformUI.getWorkbench();
+               IEditorRegistry editorRegistry = workbench.getEditorRegistry();
+               IEditorDescriptor descriptor = editorRegistry.getDefaultEditor(file.getName(), getContentType(file));
+
+               // check the OS for in-place editor (OLE on Win32)
+               if (descriptor == null && editorRegistry.isSystemInPlaceEditorAvailable(file.getName()))
+                       descriptor= editorRegistry.findEditor(IEditorRegistry.SYSTEM_INPLACE_EDITOR_ID);
+               
+               // check the OS for external editor
+               if (descriptor == null && editorRegistry.isSystemExternalEditorAvailable(file.getName()))
+                       descriptor = editorRegistry.findEditor(IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID);
+               
+               if (descriptor != null)
+                       return descriptor.getId();
+               
+               return EditorsUI.DEFAULT_TEXT_EDITOR_ID;
+       }
+
+       public static IContentType getContentType(IFileStore fileStore) {
+               if (fileStore == null)
+                       return null;
+
+               InputStream stream= null;
+               try {
+                       stream = fileStore.openInputStream(EFS.NONE, null);
+                       return Platform.getContentTypeManager().findContentTypeFor(stream, fileStore.getName());
+               } catch (IOException e) {
+                       ZipEditorPlugin.log(e);
+                       return null;
+               } catch (CoreException e) {
+                       // Do not log FileNotFoundException (no access)
+                       if (!(e.getStatus().getException() instanceof FileNotFoundException))
+                               ZipEditorPlugin.log(e);
+                       
+                       return null;
+               } finally {
+                       try {
+                               if (stream != null)
+                                       stream.close();
+                       } catch (IOException e) {
+                               ZipEditorPlugin.log(e);
+                       }
+               }
+       }
+
+       private static IFile getWorkspaceFile(IFileStore fileStore) {
+               IWorkspace workspace = ResourcesPlugin.getWorkspace();
+               final IFile[] files = filterNonExistentFiles(workspace.getRoot().
+                               findFilesForLocation(new Path(fileStore.toURI().getPath())));
+               if (files == null || files.length == 0)
+                       return null;
+               if (files.length == 1)
+                       return files[0];
+               if (isUIThread()) {
+                       return selectWorkspaceFile(files);
+               } else {
+                       final IFile[] result = { null };
+                       Display.getDefault().syncExec(new Runnable() {
+                               public void run() {
+                                       result[0] = selectWorkspaceFile(files);
+                               }
+                       });
+                       return result[0];
+               }
+       }
+       
+       private static IFile selectWorkspaceFile(IFile[] files) {
+               ElementListSelectionDialog dialog = new ElementListSelectionDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), new LabelProvider() {
+                       public String getText(Object element) {
+                               if (element instanceof IFile) {
+                                       IPath path =  ((IFile) element).getFullPath();
+                                       return path != null ? path.toString() : ""; //$NON-NLS-1$
+                               }
+                               return super.getText(element);
+                       }
+               });
+               dialog.setElements(files);
+               dialog.setTitle(Messages.getString("OpenFileOperation.0")); //$NON-NLS-1$
+               dialog.setMessage(Messages.getString("OpenFileOperation.1")); //$NON-NLS-1$
+               if (dialog.open() == Window.OK)
+                       return (IFile) dialog.getFirstResult();
+               return null;
+       }
+
+       private static IFile[] filterNonExistentFiles(IFile[] files){
+               if (files == null)
+                       return null;
+
+               int length= files.length;
+               ArrayList existentFiles = new ArrayList(length);
+               for (int i = 0; i < length; i++) {
+                       if (files[i].exists())
+                               existentFiles.add(files[i]);
+               }
+               return (IFile[]) existentFiles.toArray(new IFile[existentFiles.size()]);
+       }
+
+       public static void readAndWrite(InputStream in, OutputStream out, boolean closeOut) throws IOException {
+               try {
+                       if (in != null) {
+                               byte[] buf = new byte[8000];
+                               for (int count = 0; (count = in.read(buf)) != -1; ) {
+                                       out.write(buf, 0, count);
+                               }
+                       }
+               } finally {
+                       if (in != null)
+                               in.close();
+                       if (closeOut)
+                               out.close();
+               }
+       }
+       
+       public static boolean allNodesAreFileNodes(IStructuredSelection selection) {
+               for (Iterator it = selection.iterator(); it.hasNext();) {
+                       Object object = it.next();
+                       if (!(object instanceof Node))
+                               return false;
+                       Node node = (Node) object;
+                       if (node.isFolder())
+                               return false;
+               }
+               return true;
+       }
+       
+       public static Node[] getSelectedNodes(ISelection selection) {
+               if (!(selection instanceof IStructuredSelection))
+                       return new Node[0];
+               Object[] objects = ((IStructuredSelection) selection).toArray();
+               Node[] nodes = new Node[objects.length];
+               System.arraycopy(objects, 0, nodes, 0, objects.length);
+               return nodes;
+       }
+
+       private Utils() {
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/ZipContentProvider.java b/org.tizen.common.externals/src/zipeditor/ZipContentProvider.java
new file mode 100644 (file)
index 0000000..d9c2fd0
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+import zipeditor.model.Node;
+import zipeditor.model.ZipContentDescriber;
+import zipeditor.model.ZipModel;
+
+public class ZipContentProvider implements ITreeContentProvider {
+       private int fMode = PreferenceConstants.VIEW_MODE_TREE;
+       private Map fModels = new HashMap();
+       private boolean fDisposeModel = true;
+
+       public ZipContentProvider() {
+       }
+
+       public ZipContentProvider(int mode) {
+               fMode = mode;
+       }
+
+       public Object[] getChildren(Object parentElement) {
+               if (parentElement instanceof Node)
+                       return getNodeChildren((Node) parentElement);
+               else if (parentElement instanceof IFile)
+                       return getFileChildren((IFile) parentElement);
+               return new Object[0];
+       }
+
+       private Object[] getNodeChildren(Node node) {
+               fModels.put(null, node.getModel());
+               if ((fMode & PreferenceConstants.VIEW_MODE_TREE) > 0)
+                       return node.getChildren();
+               else {
+                       List result = new ArrayList();
+                       addChildren(result, node, 0);
+                       return result.toArray();
+               }
+       }
+
+       private void addChildren(List list, Node node, int depth) {
+               Node[] children = node.getChildren();
+               for (int i = 0; i < children.length; i++) {
+                       Node child = children[i];
+                       addChildren(list, child, depth + 1);
+                       boolean foldersVisible = (fMode & PreferenceConstants.VIEW_MODE_FOLDERS_VISIBLE) > 0;
+                       if (foldersVisible || !child.isFolder()) {
+                               boolean allInOneLayer = (fMode & PreferenceConstants.VIEW_MODE_FOLDERS_ONE_LAYER) > 0;
+                               if (depth == 0 || allInOneLayer)
+                                       list.add(child);
+                       }
+               }
+       }
+
+       private Object[] getFileChildren(IFile file) {
+               if (!isForUs(file))
+                       return new Object[0];
+               try {
+                       ZipModel model = getModel(file);
+                       while (model.isInitializing()) {
+                               try {
+                                       Thread.sleep(100);
+                               } catch (Exception ignore) {
+                               }
+                       }
+                       return getNodeChildren(model.getRoot());
+               } catch (CoreException e) {
+                       ZipEditorPlugin.log(e);
+                       return new Object[0];
+               }
+       }
+       
+       private ZipModel getModel(IFile file) throws CoreException {
+               ZipModel model = (ZipModel) fModels.get(file);
+               if (model == null)
+                       fModels.put(file, model = new ZipModel(file.getLocation().toFile(),
+                                       file.getContents(), file.isReadOnly()));
+               return model;
+       }
+
+       public Object getParent(Object element) {
+               return element instanceof Node ? ((Node) element).getParent() : null;
+       }
+
+       public boolean hasChildren(Object element) {
+               if (element instanceof IFile)
+                       return isForUs((IFile) element);
+               return getChildren(element).length > 0;
+       }
+
+       public Object[] getElements(Object inputElement) {
+               return getChildren(inputElement);
+       }
+
+       public void dispose() {
+               disposeModels();
+       }
+
+       private void disposeModels() {
+               if (fModels != null) {
+                       for (Iterator it = fModels.values().iterator(); it.hasNext();) {
+                               ZipModel model = (ZipModel) it.next();
+                               if (fDisposeModel)
+                                       model.dispose();
+                       }
+                       fModels.clear();
+               }
+       }
+
+       public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+               if (newInput == null)
+                       disposeModels();
+       }
+
+       public static boolean isForUs(IFile file) {
+               try {
+                       IContentDescription contentDescription = file.getContentDescription();
+                       if (contentDescription == null)
+                               return false;
+                       if (contentDescription.getContentType() == null)
+                               return false;
+                       String contentTypeId = contentDescription.getContentType().getId();
+                       return ZipContentDescriber.isForUs(contentTypeId);
+               } catch (CoreException e) {
+                       ZipEditorPlugin.log(e);
+                       return false;
+               }
+       }
+
+       public void disposeModel(boolean enable) {
+               fDisposeModel = enable;
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/ZipEditor.java b/org.tizen.common.externals/src/zipeditor/ZipEditor.java
new file mode 100644 (file)
index 0000000..a36ca85
--- /dev/null
@@ -0,0 +1,1106 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.ColumnPixelData;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IElementComparer;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.FileTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.IPathEditorInput;
+import org.eclipse.ui.IPersistableElement;
+import org.eclipse.ui.IStorageEditorInput;
+import org.eclipse.ui.IURIEditorInput;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.actions.ActionContext;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.dialogs.SaveAsDialog;
+import org.eclipse.ui.part.EditorPart;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.progress.UIJob;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+import org.eclipse.ui.views.framelist.BackAction;
+import org.eclipse.ui.views.framelist.ForwardAction;
+import org.eclipse.ui.views.framelist.FrameList;
+import org.eclipse.ui.views.framelist.GoIntoAction;
+import org.eclipse.ui.views.framelist.UpAction;
+
+import zipeditor.actions.ActionMessages;
+import zipeditor.actions.CollapseAllAction;
+import zipeditor.actions.NewFolderAction;
+import zipeditor.actions.OpenActionGroup;
+import zipeditor.actions.RenameNodeAction;
+import zipeditor.actions.ReverseSelectionAction;
+import zipeditor.actions.SelectAllAction;
+import zipeditor.actions.SelectPatternAction;
+import zipeditor.actions.SortAction;
+import zipeditor.actions.ToggleViewModeAction;
+import zipeditor.actions.ZipActionGroup;
+import zipeditor.model.IModelListener;
+import zipeditor.model.Node;
+import zipeditor.model.NodeProperty;
+import zipeditor.model.ZipModel;
+import zipeditor.model.ZipModel.IErrorReporter;
+import zipeditor.model.ZipNodeProperty;
+
+public class ZipEditor extends EditorPart implements IPropertyChangeListener, IErrorReporter
+               /*,IPersistableEditor*/ {
+       static class NodeComparer implements IElementComparer {
+               public boolean equals(Object a, Object b) {
+                       return a instanceof Node && b instanceof Node ? ((Node) a).getFullPath().equals(((Node) b).getFullPath()) : a
+                                       .equals(b);
+               }
+
+               public int hashCode(Object element) {
+                       return ((Node) element).getFullPath().hashCode();
+               }
+       };
+
+       private class ModelListener extends UIJob implements IModelListener {
+               public ModelListener() {
+                       super(Messages.getString("ZipEditor.11")); //$NON-NLS-1$
+               }
+
+               private ModelChangeEvent fModelChangeEvent;
+               private String fOriginalPartName;
+               private Object jobFamily = new Object();
+
+               public void modelChanged(ModelChangeEvent event) {
+                       if (fModelChangeEvent != null && !event.isInitFinished())
+                               return;
+                       fModelChangeEvent = event;
+                       long scheduleTime = 0;
+                       if (event.isInitializing() && !event.isInitStarted() && !event.isInitFinished())
+                               scheduleTime = 2000;
+                       if (event.isInitFinished()) {
+                               Job[] jobs = Platform.getJobManager().find(jobFamily);
+                               if (jobs != null) {
+                                       for (int i = 0; i < jobs.length; i++) {
+                                               jobs[i].cancel();
+                                       }
+                               }
+                       }
+                       setPriority(Job.INTERACTIVE);
+                       schedule(scheduleTime);
+               }
+               
+               public boolean belongsTo(Object family) {
+                       return family == jobFamily;
+               }
+               
+               public IStatus runInUIThread(IProgressMonitor monitor) {
+                       if (!monitor.isCanceled())
+                               doRun();
+                       fModelChangeEvent = null;
+                       return Status.OK_STATUS;
+               }
+
+               private void doRun() {
+                       if (!fZipViewer.getControl().isDisposed()) {
+                               fZipViewer.getControl().setRedraw(false);
+                               fZipViewer.refresh();
+                               fZipViewer.getControl().setRedraw(true);
+                       }
+                       if (fOutlinePage != null && !fOutlinePage.getControl().isDisposed()) {
+                               if (fOutlinePage.getInput() == null)
+                                       fOutlinePage.setInput(fModel.getRoot());
+                               else
+                                       fOutlinePage.refresh();
+                       }
+                       firePropertyChange(PROP_DIRTY);
+                       if (fModelChangeEvent != null && fModelChangeEvent.isInitializing()) {
+                               String suffix = Messages.getString("ZipEditor.10"); //$NON-NLS-1$
+                               if (!getPartName().endsWith(suffix)) {
+                                       fOriginalPartName = getPartName();
+                                       setPartName(fOriginalPartName + suffix);
+                               }                                                       
+                       } else if (fOriginalPartName != null) {
+                               setPartName(fOriginalPartName);
+                               fOriginalPartName = null;
+                       }
+               }
+       };
+
+       private class InputFileListener implements IResourceChangeListener, IResourceDeltaVisitor {
+               public void resourceChanged(IResourceChangeEvent event) {
+                       if (event.getType() == IResourceChangeEvent.POST_CHANGE) {
+                               IResourceDelta delta = event.getDelta();
+                               try {
+                                       delta.accept(this);
+                               } catch (CoreException e) {
+                                       ZipEditorPlugin.log(e);
+                               }
+                       }
+               }
+               public boolean visit(IResourceDelta delta) throws CoreException {
+                       IResource resource = delta.getResource();
+                       if (resource instanceof IFile) {
+                               IFile file = (IFile)resource;
+                               IEditorInput input = doGetEditorInput();
+                               if (input instanceof IFileEditorInput && file.equals(
+                                               ((IFileEditorInput) input).getFile())) {
+                                       if (delta.getKind() == IResourceDelta.REMOVED ||
+                                                       delta.getKind() == IResourceDelta.REPLACED)
+                                               close();
+                                       return false;
+                               }
+                       }
+                       return true;
+               }
+       };
+       
+       private class DelegateEditorInput implements IEditorInput {
+           private IEditorInput delegate;
+
+               private DelegateEditorInput(IEditorInput delegate) {
+               this.delegate = delegate;
+               }
+
+               public boolean exists() {
+               return delegate.exists();
+           }
+
+           public ImageDescriptor getImageDescriptor() {
+               return delegate.getImageDescriptor();
+           }
+
+           public String getName() {
+               return delegate.getName();
+           }
+
+           public IPersistableElement getPersistable() {
+               return delegate.getPersistable();
+           }
+
+           public String getToolTipText() {
+               return delegate.getToolTipText();
+           }
+
+           public Object getAdapter(Class adapter) {
+               return null;
+           }
+       }
+       
+       private StructuredViewer fZipViewer;
+       private IToolBarManager fToolBar;
+       private ZipActionGroup fZipActionGroup;
+       private OpenActionGroup fOpenActionGroup;
+       private Map fActions = new HashMap();
+       private IResourceChangeListener fInputFileListener;
+       private ZipModel fModel;
+       private long fModelModified;
+       private ZipOutlinePage fOutlinePage;
+       private FrameList fFrameList;
+       private IMemento fState;
+       private boolean fCheckedDeletion;
+       private ISelectionChangedListener fOutlineSelectionChangedListener;
+       private DisposeListener fTableDisposeListener = new DisposeListener() {
+               public void widgetDisposed(DisposeEvent e) {
+                       storeTableColumnPreferences();
+               }
+       };
+
+       public final static String ACTION_TOGGLE_MODE = "ToggleViewMode"; //$NON-NLS-1$
+       public final static String ACTION_COLLAPSE_ALL = "CollapseAll"; //$NON-NLS-1$
+       public final static String ACTION_SELECT_ALL = "SelectAll"; //$NON-NLS-1$
+       public final static String ACTION_SELECT_PATTERN = "SelectPattern"; //$NON-NLS-1$
+       public final static String ACTION_REVERSE_SELECTION = "ReverseSelection"; //$NON-NLS-1$
+       public final static String ACTION_NEW_FOLDER = "NewFolder"; //$NON-NLS-1$
+       public final static String ACTION_BACK = "Back"; //$NON-NLS-1$
+       public final static String ACTION_FORWARD = "Forward"; //$NON-NLS-1$
+       public final static String ACTION_UP = "Up"; //$NON-NLS-1$
+       public final static String ACTION_GO_INTO = "GoInto"; //$NON-NLS-1$
+       public final static String ACTION_RENAME = "Rename"; //$NON-NLS-1$
+       
+       public void doSave(IProgressMonitor monitor) {
+               IEditorInput input = doGetEditorInput();
+               if (input instanceof IFileEditorInput)
+                       internalSave(((IFileEditorInput) input).getFile().getLocation(), monitor);
+               else if (input instanceof IPathEditorInput)
+                       internalSave(((IPathEditorInput) input).getPath(), monitor);
+               else if (input instanceof IURIEditorInput)
+                       internalSave(new Path(((IURIEditorInput) input).getURI().getPath()), monitor);
+               else
+                       fModel.logError("The input " + input + " cannot be saved"); //$NON-NLS-1$ //$NON-NLS-2$
+       }
+       
+       private void internalSave(IPath locationPath, IProgressMonitor monitor) {
+               Node root = getRootNode();
+               monitor.beginTask(Messages.getString("ZipEditor.3"), 100); //$NON-NLS-1$
+               monitor.worked(1);
+               int totalWork = Utils.computeTotalNumber(root.getChildren(), monitor);
+               SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, 99);
+               monitor.setTaskName(Messages.getString("ZipEditor.2")); //$NON-NLS-1$
+               monitor.subTask(locationPath.lastSegment());
+               subMonitor.beginTask(Messages.getString("ZipEditor.2") + locationPath, totalWork); //$NON-NLS-1$
+               InputStream in = null;
+               try {
+                       in = root.getModel().save(ZipModel.typeFromName(locationPath.lastSegment()), subMonitor);
+                       IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(locationPath);
+                       IEditorInput newInput = null;
+                       if (file != null) {
+                               newInput = internalSaveWorkspaceFile(file, in, monitor);
+                       } else {
+                               newInput = internalSaveLocalFile(locationPath.toFile(), in);
+                       }
+                       doFirePropertyChange(PROP_DIRTY);
+                       setInput(newInput);
+                       if (Utils.isUIThread())
+                               setPartName(newInput.getName());
+                       else {
+                               final String newName = newInput.getName();
+                               getSite().getShell().getDisplay().syncExec(new Runnable() {
+                                       public void run() {
+                                               setPartName(newName);
+                                       }
+                               });
+                       }
+                       doRevert();
+               } catch (final Exception e) {
+                       if (Utils.isUIThread()) {
+                               doShowErrorDialog(e);
+                       } else {
+                       getSite().getShell().getDisplay().syncExec(new Runnable() {
+                               public void run() {
+                                       doShowErrorDialog(e);
+                               }
+                       });
+                       }
+               } finally {
+                       if (in != null) {
+                               try {
+                                       in.close();
+                               } catch (IOException ignore) {
+                               }
+                       }
+                       subMonitor.done();
+                       monitor.done();
+               }
+       }
+
+       private void doShowErrorDialog(Throwable e) {
+               ZipEditorPlugin.showErrorDialog(getSite().getShell(),
+                               Messages.getFormattedString("ZipEditor.12", getEditorInput().getName()), //$NON-NLS-1$
+                               e);
+       }
+
+       private IEditorInput internalSaveWorkspaceFile(IFile file, InputStream in, IProgressMonitor monitor) throws Exception {
+               if (file.exists())
+                       file.setContents(in, true, true, monitor);
+               else
+                       file.create(in, true, monitor);
+               return new FileEditorInput(file);
+       }
+
+       private IEditorInput internalSaveLocalFile(File file, InputStream in) throws Exception {
+               Utils.readAndWrite(in, new FileOutputStream(file), true);
+               IFileStore fileStore = EFS.getLocalFileSystem().getStore(new Path(file.getParentFile().getAbsolutePath()));
+               fileStore = fileStore.getChild(file.getName());
+               return new LocalFileEditorInput(fileStore);
+       }
+
+       public void doSaveAs() {
+               SaveAsDialog dialog = new SaveAsDialog(getSite().getShell());
+               IEditorInput input = doGetEditorInput();
+               IFile original = (input instanceof IFileEditorInput) ? ((IFileEditorInput) input).getFile() : null;
+               if (original != null)
+                       dialog.setOriginalFile(original);
+
+               dialog.create();
+               if (dialog.open() == Window.CANCEL) {
+                       return;
+               }
+               final IPath filePath = dialog.getResult();
+               if (filePath == null)
+                       return;
+
+               IRunnableWithProgress op = new IRunnableWithProgress() {
+                       public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+                               internalSave(ResourcesPlugin.getWorkspace().getRoot().getFile(filePath).getLocation(), monitor);
+                       }
+               };
+               try {
+                       getSite().getWorkbenchWindow().run(true, true, op);
+               } catch (Exception e) {
+                       fModel.logError(e);
+               }
+       }
+
+       public void doRevert() {
+               if (fModel != null)
+                       fModel.dispose();
+               fModel = null;
+               doFirePropertyChange(PROP_DIRTY);
+               setViewerInput(fZipViewer);
+       }
+
+       public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+               setSite(site);
+               setInput(input);
+               setPartName(input.getName());
+               fInputFileListener = new InputFileListener();
+               ResourcesPlugin.getWorkspace().addResourceChangeListener(fInputFileListener);
+               getPreferenceStore().addPropertyChangeListener(this);
+       }
+       
+       protected void setInput(IEditorInput input) {
+        if (input != getEditorInput()) {
+            super.setInput(input);
+            doFirePropertyChange(PROP_INPUT);
+               if (fOutlinePage != null)
+                       fOutlinePage.setInput(fModel.getRoot());
+        }
+       }
+       
+       private void doFirePropertyChange(final int property) {
+        if (Utils.isUIThread()) {
+               firePropertyChange(property);
+        } else {
+               getSite().getShell().getDisplay().syncExec(new Runnable() {
+                       public void run() {
+                       firePropertyChange(property);
+                       }
+               });
+        }
+       }
+
+       public void close() {
+               Display display = getSite().getShell().getDisplay();
+               display.asyncExec(new Runnable() {
+                       public void run() {
+                               getSite().getPage().closeEditor(ZipEditor.this, false);
+                       }
+               });
+       }
+       
+       public void dispose() {
+               if (fInputFileListener != null) {
+                       ResourcesPlugin.getWorkspace().removeResourceChangeListener(fInputFileListener);
+                       fInputFileListener = null;
+               }
+               if (fOutlinePage != null) {
+                       fOutlinePage.removeSelectionChangedListener(fOutlineSelectionChangedListener);
+                       fOutlinePage.dispose();
+               }
+               getPreferenceStore().removePropertyChangeListener(this);
+               fActions.clear();
+               fActions = null;
+               fOpenActionGroup.dispose();
+               fZipActionGroup.dispose();
+               super.dispose();                
+       }
+
+       private ZipModel createModel() {
+               Object[] info = getEditorInputFileInfo(true);
+               File file = (File) info[0];
+               InputStream in = (InputStream) info[1];
+               boolean isReadOnly = ((Boolean) info[2]).booleanValue();
+               if (in != null && file != null && !file.exists()) {
+                       try {
+                               file = File.createTempFile("tmp", null); //$NON-NLS-1$
+                               file.deleteOnExit();
+                               Utils.readAndWrite(in, new FileOutputStream(file), true);
+                               in = new FileInputStream(file);
+                       } catch (IOException e) {
+                               ZipEditorPlugin.log(e);
+                       }
+               }
+               return new ZipModel(file, in, isReadOnly, this);
+       }
+       
+       public void reportError(IStatus message) {
+               ZipEditorActionBarContributor contributor = (ZipEditorActionBarContributor) getEditorSite().getActionBarContributor();
+               contributor.reportError(this, message);
+       }
+       
+       private Object[] getEditorInputFileInfo(boolean getInputStream) {
+               IEditorInput input = doGetEditorInput();
+               IPath path = null;
+               InputStream in = null;
+               File file = null;
+               Boolean readonly = Boolean.TRUE;
+               if (input instanceof IFileEditorInput) {
+                       path = ((IFileEditorInput) input).getFile().getLocation();
+                       file = path.toFile();
+                       if (getInputStream) {
+                               try {
+                                       in = ((IFileEditorInput) input).getFile().getContents();
+                               } catch (CoreException e) {
+                                       throw new RuntimeException(e);
+                               }
+                       }
+                       readonly = new Boolean(((IFileEditorInput) input).getFile().isReadOnly());
+               } else {
+                       if (input instanceof IPathEditorInput) {
+                               path = ((IPathEditorInput) input).getPath();
+                               file = path.toFile();
+                               readonly = new Boolean(!file.canWrite());
+                       }
+                       if (input instanceof IStorageEditorInput) {
+                               try {
+                                       if (path == null) {
+                                               path = ((IStorageEditorInput) input).getStorage().getFullPath();
+                                               if (path != null)
+                                                       file = path.toFile();
+                                       }
+                                       if (getInputStream)
+                                               in = ((IStorageEditorInput) input).getStorage().getContents();
+                                       readonly = new Boolean(((IStorageEditorInput) input).getStorage().isReadOnly());
+                               } catch (CoreException e) {
+                                       ZipEditorPlugin.log(e);
+                               }
+                       }
+                       if (path == null && input instanceof IURIEditorInput) {
+                               try {
+                                       file = new File(((IURIEditorInput) input).getURI());
+                                       path = new Path(file.getAbsolutePath());
+                                       // file exists cause it can be read but is set readonly
+                                       readonly = new Boolean(!file.canWrite() && file.canRead());
+                                       if (getInputStream)
+                                               in = (((IURIEditorInput) input).getURI().toURL()).openStream();
+                               } catch (Exception e) {
+                                       ZipEditorPlugin.log(e);
+                               }
+                       }
+               }
+               return new Object[] { file, in, readonly };
+       }
+       
+       private IEditorInput doGetEditorInput() {
+               IEditorInput input = getEditorInput();
+               return input instanceof DelegateEditorInput ? ((DelegateEditorInput) input).delegate : input;
+       }
+       
+       public boolean isDirty() {
+               return fModel != null && fModel.isDirty() && !fModel.isReadonly();
+       }
+
+       public boolean isSaveAsAllowed() {
+               return true;
+       }
+
+       public void createPartControl(Composite parent) {
+               Composite control = new Composite(parent, SWT.NONE);
+               GridLayout layout = new GridLayout();
+               layout.marginWidth = layout.marginHeight = 0;
+               control.setLayout(layout);
+               createContent(control, getMode());
+       }
+       
+       private void createContent(Composite parent, int mode) {
+               createControls(parent, mode);
+               createActions(mode);
+               fillToolBar(fToolBar, mode);
+               addViewerListener(getViewer());
+       }
+       
+       private void createControls(Composite parent, int mode) {
+               fToolBar = createToolBar(parent);
+               fZipViewer = createZipViewer(parent, mode);
+       }
+       
+       private ToolBarManager createToolBar(Composite parent) {
+               ToolBarManager bar = new ToolBarManager(SWT.HORIZONTAL | SWT.FLAT);
+               Control control = bar.createControl(parent);
+               control.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+               return bar;
+       }
+       
+       private void fillToolBar(IToolBarManager bar, int mode) {
+               if ((mode & PreferenceConstants.VIEW_MODE_TREE) == 0
+                               && (mode & PreferenceConstants.VIEW_MODE_FOLDERS_VISIBLE) > 0) {
+                       bar.add(getAction(ACTION_BACK));
+                       bar.add(getAction(ACTION_FORWARD));
+                       bar.add(getAction(ACTION_UP));
+                       bar.add(new Separator());
+               }
+               bar.add(getAction(ACTION_TOGGLE_MODE));
+               fOpenActionGroup.fillToolBarManager(bar);
+               fZipActionGroup.fillToolBarManager(bar, mode);
+               bar.add(new Separator());
+               if ((mode & PreferenceConstants.VIEW_MODE_TREE) > 0) {
+                       bar.add(new Separator());
+                       bar.add(getAction(ACTION_COLLAPSE_ALL));
+               }
+               bar.update(false);
+       }
+
+       public void updateView(int mode, boolean savePreferences) {
+               Composite parent = fZipViewer.getControl().getParent();
+               ISelection selection = fZipViewer.getSelection();
+               ((ZipContentProvider) fZipViewer.getContentProvider()).disposeModel(false);
+               Control[] children = parent.getChildren();
+               for (int i = 0; i < children.length; i++) {
+                       if (!savePreferences)
+                               children[i].removeDisposeListener(fTableDisposeListener);
+                       children[i].dispose();
+               }
+               createContent(parent, mode);
+               parent.layout();
+               fZipViewer.setSelection(selection);
+               fZipViewer.getControl().setFocus();
+               ((ZipContentProvider) fZipViewer.getContentProvider()).disposeModel(true);
+       }
+       
+       private StructuredViewer createZipViewer(Composite parent, int mode) {
+               StructuredViewer viewer = null;
+               if ((mode & PreferenceConstants.VIEW_MODE_TREE) > 0) {
+                       viewer = new TreeViewer(parent);
+               } else {
+                       viewer = createTableViewer(parent);
+               }
+               
+               viewer.setContentProvider(new ZipContentProvider(mode));
+               viewer.setLabelProvider(new ZipLabelProvider());
+               viewer.setSorter(new ZipSorter(PreferenceConstants.PREFIX_EDITOR));
+               viewer.setComparer(new NodeComparer());
+               viewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH));
+               MenuManager manager = new MenuManager();
+               manager.setRemoveAllWhenShown(true);
+               final IEditorInput originalInput = doGetEditorInput();
+               manager.addMenuListener(new IMenuListener() {
+                       public void menuAboutToShow(IMenuManager manager) {
+                               handleContextMenuAboutToShow(manager);
+                               // no better idea to prevent other items being added to the menu
+                               if (!(getEditorInput() instanceof DelegateEditorInput))
+                                       ZipEditor.super.setInput(new DelegateEditorInput(originalInput));
+                       }
+               });
+               Menu contextMenu = manager.createContextMenu(viewer.getControl());
+               contextMenu.addListener(SWT.Hide, new Listener() {
+                       public void handleEvent(Event event) {
+                               if (getEditorInput() instanceof DelegateEditorInput)
+                                       ZipEditor.super.setInput(originalInput);
+                       }
+               });
+               viewer.getControl().setMenu(contextMenu);
+               getSite().registerContextMenu(manager, fZipViewer);
+               
+               viewer.getControl().addFocusListener(new FocusAdapter() {
+                       public void focusGained(FocusEvent e) {
+                               ZipEditorPlugin.getDefault().checkFilesForModification(fModel);
+                               firePropertyChange(PROP_DIRTY);
+                       }
+               });
+
+               setViewerInput(viewer);
+               initDragAndDrop(viewer);
+
+               return viewer;
+       }
+       
+       private void addViewerListener(StructuredViewer viewer) {
+               viewer.addDoubleClickListener(new IDoubleClickListener() {
+                       public void doubleClick(DoubleClickEvent event) {
+                               handleViewerDoubleClick();
+                       }
+               });
+               viewer.addSelectionChangedListener(new ISelectionChangedListener() {
+                       public void selectionChanged(SelectionChangedEvent event) {
+                               handleViewerSelectionChanged(event.getSelection());
+                       }
+               });
+       }
+       
+       private Object updateFrameList() {
+               Node currentNode = null;
+               for (int i = 0, n = fFrameList.size(); i < n; i++) {
+                       TableFrame tableFrame = (TableFrame) fFrameList.getFrame(i);
+                       String path = tableFrame.getInput() != null ? ((Node) tableFrame.getInput()).getPath() : null;
+                       Node node = fModel.findNode(path);
+                       if (node == null)
+                               continue;
+                       tableFrame.setInput(node);
+                       if (i == fFrameList.getCurrentIndex())
+                               currentNode = node;
+               }
+               return currentNode;
+       }
+       
+       private void setViewerInput(final StructuredViewer viewer) {
+               Object input = null;
+               if (fModel == null) {
+                       fModel = createModel();
+                       if (fModel.getZipPath() != null)
+                               fModelModified = fModel.getZipPath().lastModified();
+                       fModel.addModelListener(new ModelListener());
+                       input = fModel.getRoot();
+                       if (fFrameList != null) {
+                               Object node = updateFrameList();
+                               if (node != null)
+                                       input = node;
+                       }
+               } else {
+                       input = fModel.getRoot();
+               }
+               if (input != null) {
+                       if (Utils.isUIThread()) {
+                               viewer.setInput(input);
+                               if (fFrameList != null)
+                                       viewer.refresh(true);
+                       } else {
+                               viewer.getControl().getDisplay().syncExec(new Runnable() {
+                                       public void run() {
+                                               viewer.setInput(fModel.getRoot());
+                                       }
+                               });
+                       }
+                       if (fOutlinePage != null)
+                               fOutlinePage.setInput(fModel.getRoot());
+               } else {
+                       if (Utils.isUIThread())
+                               setViewerInputAgain(viewer);
+                       else {
+                               viewer.getControl().getDisplay().syncExec(new Runnable() {
+                                       public void run() {
+                                               setViewerInputAgain(viewer);
+                                       }
+                               });
+                       }
+               }
+       }
+       
+       private void setViewerInputAgain(final StructuredViewer viewer){
+               viewer.getControl().getDisplay().timerExec(100, new Runnable() {
+                       public void run() {
+                               setViewerInput(viewer);
+                       }
+               });
+       }
+       
+       private void handleContextMenuAboutToShow(IMenuManager manager) {
+               manager.add(new Separator(IWorkbenchActionConstants.OPEN_EXT));
+               manager.add(new Separator());
+               manager.add(getAction(ACTION_NEW_FOLDER));
+               manager.add(new Separator());
+               fOpenActionGroup.setContext(new ActionContext(fZipViewer.getSelection()));
+               fOpenActionGroup.fillContextMenu(manager);
+               fZipActionGroup.setContext(new ActionContext(fZipViewer.getSelection()));
+               fZipActionGroup.fillContextMenu(manager);
+               manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+       }
+
+       private void handleViewerDoubleClick() {
+               Node[] nodes = getSelectedNodes();
+               if (nodes == null || nodes.length == 0)
+                       return;
+               if (nodes.length == 1 && nodes[0].isFolder()) {
+                       if (fZipViewer instanceof TreeViewer) {
+                               ((TreeViewer) fZipViewer).setExpandedState(nodes[0], !((TreeViewer) fZipViewer).getExpandedState(nodes[0]));
+                               return;
+                       } else if (fZipViewer instanceof TableViewer) {
+                               ((GoIntoAction) getAction(ACTION_GO_INTO)).run();
+                               return;
+                       }
+               }
+               Utils.openFilesFromNodes(nodes);
+       }
+
+       private void handleViewerSelectionChanged(ISelection selection) {
+               activateActions();
+               fZipActionGroup.setContext(new ActionContext(selection));
+               fZipActionGroup.updateActionBars();
+               fOpenActionGroup.setContext(new ActionContext(selection));
+               fOpenActionGroup.updateActionBars();
+               IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+               int size = structuredSelection.size();
+               setStatusText(size == 0 ? null : size == 1 ?
+                               structuredSelection.getFirstElement() : Messages.getFormattedString("ZipEditor.9", new Integer(size))); //$NON-NLS-1$
+               if (size == 1)
+                       synchronizeOutlineSelection(getSelectedNodes()[0]);
+               if (fFrameList != null)
+                       ((TableFrame) fFrameList.getCurrentFrame()).setSelection(structuredSelection);
+       }
+
+       private void handleOutlineSelectionChanged() {
+               IStructuredSelection selection = (IStructuredSelection) fOutlinePage.getSelection();
+               if (selection.size() != 1)
+                       return;
+               fZipViewer.setSelection(selection, true);
+       }
+
+       private void synchronizeOutlineSelection(Node node) {
+               if (node == null || fOutlinePage == null || !fOutlinePage.isLinkingEnabled())
+                       return;
+               fOutlinePage.removeSelectionChangedListener(fOutlineSelectionChangedListener);
+               fOutlinePage.setSelection(new StructuredSelection(node));
+               fOutlinePage.addSelectionChangedListener(fOutlineSelectionChangedListener);
+       }
+
+       private void setStatusText(Object object) {
+               IWorkbenchPartSite activeSite = getSite().getPage().getActivePart() != null ?
+                               getSite().getPage().getActivePart().getSite() : getEditorSite();
+               IActionBars actionBars = activeSite instanceof IEditorSite ? ((IEditorSite) activeSite).getActionBars()
+                               : activeSite instanceof IViewSite ? ((IViewSite) activeSite).getActionBars() : null;
+               if (actionBars != null)
+                       actionBars.getStatusLineManager().setMessage(object instanceof Node
+                               ? ((Node) object).getName() : object != null ? object.toString() : null);
+       }
+
+       private TableViewer createTableViewer(Composite parent) {
+               TableViewer viewer = new TableViewer(parent, SWT.MULTI | SWT.FULL_SELECTION);
+               Table table = viewer.getTable();
+               table.setHeaderVisible(true);
+               createTableColumns(table);
+               table.addDisposeListener(fTableDisposeListener);
+               return viewer;
+       }
+       
+       private void createTableColumns(Table table) {
+               IPreferenceStore store = getPreferenceStore();
+               int sortColumn = store.getInt(PreferenceConstants.SORT_BY);
+               int sortDirection = store.getInt(PreferenceConstants.SORT_DIRECTION);
+               Integer[] visibleColumns = (Integer[]) PreferenceInitializer.split(store.getString(PreferenceConstants.VISIBLE_COLUMNS), PreferenceConstants.COLUMNS_SEPARATOR, Integer.class);
+               for (int i = 0; i < visibleColumns.length; i++) {
+                       int type = visibleColumns[i].intValue();
+                       createTableColumn(table, Messages.getString("ZipNodeProperty." + type), type, sortColumn, sortDirection); //$NON-NLS-1$
+               }
+               TableLayout layout = new TableLayout();
+               TableColumn[] columns = table.getColumns();
+               for (int i = 0; i < columns.length; i++) {
+                       int width = store.getInt(PreferenceConstants.SORT_COLUMN_WIDTH + columns[i].getData());
+                       if (width == 0)
+                               width = 150;
+                       layout.addColumnData(new ColumnPixelData(width));
+               }
+               table.setLayout(layout);
+       }
+
+       private TableColumn createTableColumn(Table table, String text, int colType, int sortColumn, int sortDirection) {
+               int style = colType == ZipNodeProperty.PACKED_SIZE || colType == NodeProperty.SIZE ? SWT.RIGHT : SWT.LEFT;
+               TableColumn column = new TableColumn(table, style);
+               column.setText(text);
+               column.setData(new Integer(colType));
+               column.setMoveable(true);
+               column.setImage(getSortImage(sortColumn == colType ? sortDirection : SWT.NONE));
+               column.addSelectionListener(new SelectionAdapter() {
+                       public void widgetSelected(SelectionEvent e) {
+                               handleSortColumnSelected((TableColumn) e.widget);
+                       }
+               });
+               return column;
+       }
+       
+       public void storeTableColumnPreferences() {
+               if (!(fZipViewer instanceof TableViewer))
+                       return;
+               Table table = ((TableViewer) fZipViewer).getTable();
+               IPreferenceStore store = getPreferenceStore();
+               TableColumn[] columns = table.getColumns();
+               int[] order = table.getColumnOrder();
+               for (int i = 0; i < columns.length; i++) {
+                       store.setValue(PreferenceConstants.SORT_COLUMN_WIDTH + columns[i].getData(), columns[i].getWidth());
+               }
+               for (int i = 0; i < order.length; i++) {
+                       order[i] = ((Integer) columns[order[i]].getData()).intValue();
+               }
+               store.setValue(PreferenceConstants.VISIBLE_COLUMNS, PreferenceInitializer.join(order, PreferenceConstants.COLUMNS_SEPARATOR));
+       }
+
+       private void handleSortColumnSelected(TableColumn column) {
+               IPreferenceStore store = getPreferenceStore();
+               int sortColumn = store.getInt(PreferenceConstants.SORT_BY);
+               int sortDirection = store.getInt(PreferenceConstants.SORT_DIRECTION);
+               
+               if (((Integer) column.getData()).intValue() == sortColumn) {
+                       sortDirection = sortDirection == SWT.UP ? SWT.DOWN : SWT.UP;
+                       column.setImage(getSortImage(sortDirection));
+               } else {
+                       sortColumn = ((Integer) column.getData()).intValue();
+                       column.setImage(getSortImage(sortDirection = SWT.UP));
+                       TableColumn[] columns = column.getParent().getColumns();
+                       for (int i = 0; i < columns.length; i++) {
+                               if (columns[i] != column)
+                                       columns[i].setImage(getSortImage(SWT.NONE));
+                       }
+               }
+               store.setValue(PreferenceConstants.SORT_DIRECTION, sortDirection);
+               store.setValue(PreferenceConstants.SORT_BY, sortColumn);
+               ((ZipSorter) fZipViewer.getSorter()).update();
+               fZipViewer.refresh();
+       }
+
+       private Image getSortImage(int direction) {
+               if (!getPreferenceStore().getBoolean(PreferenceConstants.PREFIX_EDITOR + PreferenceConstants.SORT_ENABLED))
+                       direction = 0;
+               switch (direction) {
+               default:
+                       return ZipEditorPlugin.getImage("icons/sort_none.gif"); //$NON-NLS-1$
+               case SWT.UP:
+                       return ZipEditorPlugin.getImage("icons/sort_asc.gif"); //$NON-NLS-1$
+               case SWT.DOWN:
+                       return ZipEditorPlugin.getImage("icons/sort_desc.gif"); //$NON-NLS-1$
+               }
+       }
+
+       private void createActions(int mode) {
+               fZipActionGroup = new ZipActionGroup(this);
+               fOpenActionGroup = new OpenActionGroup(getViewer(), false);
+               setAction(ACTION_NEW_FOLDER, new NewFolderAction(getViewer()));
+               ToggleViewModeAction toggleViewModeAction = new ToggleViewModeAction(this, ActionMessages.getString("ToggleViewModeAction.0"), PreferenceConstants.PREFIX_EDITOR, PreferenceConstants.VIEW_MODE_TREE); //$NON-NLS-1$
+               toggleViewModeAction.setToolTipText(ActionMessages.getString("ToggleViewModeAction.1")); //$NON-NLS-1$
+               toggleViewModeAction.setImageDescriptor(ZipEditorPlugin.getImageDescriptor("icons/togglemode.gif")); //$NON-NLS-1$
+               setAction(ACTION_TOGGLE_MODE, toggleViewModeAction);
+
+               setAction(ACTION_COLLAPSE_ALL, new CollapseAllAction(getViewer()));
+               setAction(ACTION_SELECT_ALL, new SelectAllAction(getViewer()));
+               setAction(ACTION_SELECT_PATTERN, new SelectPatternAction(getViewer()));
+               setAction(ACTION_REVERSE_SELECTION, new ReverseSelectionAction(getViewer()));
+               setAction(ACTION_RENAME, new RenameNodeAction(getViewer()));
+
+               fFrameList = createFrameList(mode);
+               if (fFrameList != null) {
+                       setAction(ACTION_BACK, new BackAction(fFrameList));
+                       setAction(ACTION_FORWARD, new ForwardAction(fFrameList));
+                       setAction(ACTION_UP, new UpAction(fFrameList));
+                       setAction(ACTION_GO_INTO, new GoIntoAction(fFrameList));
+               }
+
+               activateActions();
+       }
+
+       private FrameList createFrameList(int mode) {
+               if (!(fZipViewer instanceof TableViewer))
+                       return null;
+               TableViewerFrameSource frameSource = new TableViewerFrameSource((TableViewer) fZipViewer);
+               FrameList frameList = new FrameList(frameSource);
+               frameList.addPropertyChangeListener(new IPropertyChangeListener() {
+                       public void propertyChange(PropertyChangeEvent event) {
+                               String inputName = getEditorInput().getName();
+                               TableFrame frame = (TableFrame) ((FrameList) event.getSource()).getCurrentFrame();
+                               Node node = (Node) frame.getInput();
+                               if (node != null){
+                                       String frameName = node.getPath();
+                                       frameName = inputName + (frameName.length() > 0 ? " - " + frameName : new String()); //$NON-NLS-1$
+                                       setPartName(frameName);
+                               }
+                       }
+               });
+               frameSource.connectTo(frameList);
+               setPartName(getEditorInput().getName());
+               if (fState != null && (mode & PreferenceConstants.VIEW_MODE_FOLDERS_VISIBLE) > 0) {
+                       TableFrame currentFrame = (TableFrame) frameList.getCurrentFrame();
+                       currentFrame.restoreState(fState, fModel);
+                       if (fModel.getRoot() == currentFrame.getInput())
+                               fZipViewer.setSelection(currentFrame.getSelection());
+                       else
+                               frameList.gotoFrame(currentFrame);
+               }
+               return frameList;
+       }
+       
+       private void setAction(String name, IAction action) {
+               fActions.put(name, action);
+       }
+       
+       private IAction getAction(String name) {
+               return (IAction) fActions.get(name);
+       }
+
+       private void initDragAndDrop(StructuredViewer viewer) {
+               int ops = DND.DROP_DEFAULT | DND.DROP_COPY;
+               Transfer[] transfers = new Transfer[] { FileTransfer.getInstance() };
+
+        viewer.addDragSupport(ops, transfers, new ZipEditorDragAdapter(viewer));
+        viewer.addDropSupport(ops | DND.DROP_DEFAULT, transfers, new ZipEditorDropAdapter(viewer));
+       }
+       
+       public IPreferenceStore getPreferenceStore() {
+               return ZipEditorPlugin.getDefault().getPreferenceStore();
+       }
+       
+       public Object getAdapter(Class adapter) {
+               if (IContentOutlinePage.class.equals(adapter)) {
+                       if (fOutlinePage == null) {
+                               fOutlinePage = new ZipOutlinePage();
+                               if (fOutlineSelectionChangedListener == null)
+                                       fOutlineSelectionChangedListener = new ISelectionChangedListener() {
+                                               public void selectionChanged(SelectionChangedEvent event) {
+                                                       handleOutlineSelectionChanged();
+                                               }
+                               };
+                               fOutlinePage.addSelectionChangedListener(fOutlineSelectionChangedListener);
+                               getEditorSite().getShell().getDisplay().asyncExec(new Runnable() {
+                                       public void run() {
+                                               fOutlinePage.setInput(fModel.getRoot());
+                                       }
+                               });
+                       }
+                       return fOutlinePage;
+               }
+               return super.getAdapter(adapter);
+       }
+
+       public Node[] getSelectedNodes() {
+               return Utils.getSelectedNodes(fZipViewer.getSelection());
+       }
+       
+       public void setFocus() {
+               if (fZipViewer != null)
+                       fZipViewer.getControl().setFocus();
+               activateActions();
+               checkIfFileHasBeenChangedLocaly(doGetEditorInput());
+       }
+
+       private void checkIfFileHasBeenChangedLocaly(IEditorInput editorInput) {
+               Object[] info = getEditorInputFileInfo(false);
+               File file = (File) info[0];
+               boolean readOnly = ((Boolean) info[2]).booleanValue();
+               boolean fileDeleted = file != null && !file.exists();
+               boolean fileModified = file != null && file.exists() && file.lastModified() > fModelModified;
+               if (editorInput instanceof IFileEditorInput) {
+                       fileModified = !((IFileEditorInput) editorInput).getFile().isSynchronized(IResource.DEPTH_ONE);
+               }
+               if (fileModified) {
+                       if (MessageDialog.openQuestion(getSite().getShell(),
+                                       Messages.getString("ZipEditor.4"), //$NON-NLS-1$
+                                       Messages.getString("ZipEditor.5"))) { //$NON-NLS-1$
+                               if (editorInput instanceof IFileEditorInput) {
+                                       try {
+                                               ((IFileEditorInput) editorInput).getFile().refreshLocal(IResource.DEPTH_ONE, new NullProgressMonitor());
+                                       } catch (CoreException e) {
+                                               fModel.logError(e);
+                                       }
+                               }
+                               doRevert();
+                       }
+               } else if (fileDeleted && !readOnly && !fCheckedDeletion) {
+                       fCheckedDeletion = true;
+                       MessageDialog dialog = new MessageDialog(getSite().getShell(),
+                                       Messages.getString("ZipEditor.6"), null, Messages //$NON-NLS-1$
+                                                       .getFormattedString("ZipEditor.7", editorInput //$NON-NLS-1$
+                                                                       .getName()), MessageDialog.QUESTION,
+                                       new String[] { Messages.getString("ZipEditor.13"), //$NON-NLS-1$
+                                                       Messages.getString("ZipEditor.14"), //$NON-NLS-1$
+                                                       IDialogConstants.CANCEL_LABEL }, 0);
+                       switch (dialog.open()) {
+                       case 0:
+                               close();
+                               break;
+                       case 1:
+                               doSave(new NullProgressMonitor());
+                               break;
+                       }
+               } else if (!fileDeleted) {
+                       fCheckedDeletion = false;
+               }
+       }
+
+       private void activateActions() {
+               getEditorSite().getActionBars().setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), getAction(ACTION_SELECT_ALL));
+               getEditorSite().getActionBars().setGlobalActionHandler(SelectPatternAction.ID, getAction(ACTION_SELECT_PATTERN));
+               getEditorSite().getActionBars().setGlobalActionHandler(ReverseSelectionAction.ID, getAction(ACTION_REVERSE_SELECTION));
+               getEditorSite().getActionBars().setGlobalActionHandler(ActionFactory.RENAME.getId(), getAction(ACTION_RENAME));
+               fZipActionGroup.setContext(new ActionContext(fZipViewer.getSelection()));
+               fZipActionGroup.fillActionBars(getEditorSite().getActionBars());
+               getEditorSite().getActionBars().updateActionBars();
+       }
+
+       public StructuredViewer getViewer() {
+               return fZipViewer;
+       }
+       
+       public Node getRootNode() {
+               return (Node) fZipViewer.getInput();
+       }
+
+       public int getMode() {
+               return getPreferenceStore().getInt(PreferenceConstants.PREFIX_EDITOR + PreferenceConstants.VIEW_MODE);
+       }
+       
+       public void propertyChange(PropertyChangeEvent event) {
+               if ((PreferenceConstants.PREFIX_EDITOR + PreferenceConstants.SORT_ENABLED + SortAction.SORTING_CHANGED).equals(event.getProperty()))
+                       updateView(getMode(), true);
+       }
+       
+       public void saveState(IMemento memento) {
+               if (fFrameList != null)
+                       ((TableFrame) fFrameList.getCurrentFrame()).saveState(memento);
+       }
+       
+       public void restoreState(IMemento memento) {
+               fState = memento;
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/ZipEditorActionBarContributor.java b/org.tizen.common.externals/src/zipeditor/ZipEditorActionBarContributor.java
new file mode 100644 (file)
index 0000000..4cef7dd
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * (c) Copyright 2002, 2010 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.action.ControlContribution;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.StatusLineLayoutData;
+import org.eclipse.jface.resource.JFaceColors;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.actions.RetargetAction;
+import org.eclipse.ui.part.EditorActionBarContributor;
+
+import zipeditor.actions.ReverseSelectionAction;
+import zipeditor.actions.SelectPatternAction;
+
+public class ZipEditorActionBarContributor extends EditorActionBarContributor {
+       private class ErrorStatus extends ControlContribution {
+               private ErrorStatus() {
+                       super("zipeditor.ErrorStatusContribution"); //$NON-NLS-1$
+               }
+
+               protected Control createControl(Composite parent) {
+                       Composite control = new Composite(parent, SWT.NONE);
+                       StatusLineLayoutData data = new StatusLineLayoutData();
+                       data.widthHint = Integer.MAX_VALUE;
+                       control.setLayoutData(data);
+                       GridLayout layout = new GridLayout(3, false);
+                       layout.marginHeight = layout.marginWidth = 0;
+                       layout.verticalSpacing = layout.horizontalSpacing = 0;
+                       control.setLayout(layout);
+                       errorLabel = new Label(control, SWT.LEFT);
+                       errorLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+                       errorLabel.setBackground(parent.getBackground());
+                       errorLabel.addMouseListener(new MouseAdapter() {
+                               public void mouseDoubleClick(MouseEvent e) {
+                                       showErrorDetails();
+                               }
+                       });
+                       errorLabel.setForeground(JFaceColors.getErrorText(parent.getDisplay()));
+                       ToolBar bar = new ToolBar(control, SWT.HORIZONTAL | SWT.FLAT);
+                       ToolItem delete = new ToolItem(bar, SWT.FLAT | SWT.PUSH);
+                       delete.setImage(ZipEditorPlugin.getImage(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(
+                                       ISharedImages.IMG_TOOL_DELETE)));
+                       delete.setToolTipText(Messages.getString("ZipEditorActionBarContributor.0")); //$NON-NLS-1$
+                       delete.addSelectionListener(new SelectionAdapter() {
+                               public void widgetSelected(SelectionEvent e) {
+                                       clearErrors();
+                               }
+                       });
+                       errorStatusControl = control;
+                       showCurrentError();
+                       return control;
+               }
+       }
+
+       private Composite errorStatusControl;
+       private Label errorLabel;
+       private Map errors = new HashMap();
+       private IEditorPart activeEditor;
+       private RetargetAction selectPattern;
+       private RetargetAction reverseSelection;
+
+       public void contributeToStatusLine(IStatusLineManager statusLineManager) {
+               statusLineManager.add(new ErrorStatus());
+       }
+
+       public void contributeToMenu(IMenuManager menuManager) {
+               initActions();
+               IMenuManager menu = menuManager.findMenuUsingPath("edit"); //$NON-NLS-1$
+               if (menu != null) {
+                       menu.insertAfter(ActionFactory.SELECT_ALL.getId(), selectPattern);
+                       menu.insertAfter(SelectPatternAction.ID, reverseSelection);
+               }
+       }
+       
+       private void initActions() {
+               if (selectPattern == null) {
+                       selectPattern = new RetargetAction(SelectPatternAction.ID, Messages.getString("ZipEditorActionBarContributor.1")); //$NON-NLS-1$
+                       selectPattern.setActionDefinitionId(SelectPatternAction.ID);
+                       getPage().addPartListener(selectPattern);
+               }
+               if (reverseSelection == null) {
+                       reverseSelection = new RetargetAction(ReverseSelectionAction.ID, Messages.getString("ZipEditorActionBarContributor.2")); //$NON-NLS-1$
+                       reverseSelection.setActionDefinitionId(ReverseSelectionAction.ID);
+                       getPage().addPartListener(reverseSelection);
+               }
+       }
+
+       private void showErrorDetails() {
+               if (getErrors().size() == 0)
+                       return;
+               IStatus status = (IStatus) getErrors().remove(0);
+               ZipEditorPlugin.showErrorDialog(getPage().getWorkbenchWindow().getShell(),
+                               status.getMessage(), status.getException(), false);
+               showCurrentError();
+       }
+       
+       private void clearErrors() {
+               getErrors().clear();
+               errorStatusControl.setVisible(false);
+       }
+       
+       private boolean hasErrors() {
+               return getErrors().size() > 0;
+       }
+
+       private void showCurrentError() {
+               if (errorStatusControl == null || errorStatusControl.isDisposed())
+                       return;
+               boolean hasErrors = hasErrors();
+               errorStatusControl.setVisible(hasErrors);
+               if (hasErrors) {
+                       List errorList = getErrors();
+                       errorLabel.setText("[" + errorList.size() + "] " //$NON-NLS-1$ //$NON-NLS-2$
+                                       + ((IStatus) errorList.get(0)).getMessage());
+               }
+       }
+       
+       private List getErrors() {
+               List errorList = (List) errors.get(activeEditor);
+               if (errorList == null)
+                       errors.put(activeEditor, errorList = new ArrayList());
+               return errorList;
+       }
+       
+       public void setActiveEditor(IEditorPart targetEditor) {
+               activeEditor = targetEditor;
+               showCurrentError();
+       }
+
+       public void dispose() {
+               activeEditor = null;
+               errors.clear();
+               getPage().removePartListener(selectPattern);
+       }
+
+       public void reportError(IEditorPart editor, IStatus message) {
+               activeEditor = editor;
+               getErrors().add(message);
+               getPage().getWorkbenchWindow().getShell().getDisplay().asyncExec(new Runnable() {
+                       public void run() {
+                               showCurrentError();
+                       }
+               });
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/ZipEditorDragAdapter.java b/org.tizen.common.externals/src/zipeditor/ZipEditorDragAdapter.java
new file mode 100644 (file)
index 0000000..04ec68b
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import java.io.File;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.swt.dnd.DragSourceAdapter;
+import org.eclipse.swt.dnd.DragSourceEvent;
+
+import zipeditor.model.Node;
+import zipeditor.operations.ExtractOperation;
+
+public class ZipEditorDragAdapter extends DragSourceAdapter {
+       private ISelectionProvider fSelectionProvider;
+       private String[] fTempPaths;
+
+       public ZipEditorDragAdapter(ISelectionProvider selectionProvider) {
+               fSelectionProvider = selectionProvider;
+       }
+       
+       public void dragSetData(DragSourceEvent event) {
+               final Node[] nodes = Utils.getSelectedNodes(fSelectionProvider.getSelection());
+               if (nodes.length == 0)
+                       return;
+               boolean createTempFiles = fTempPaths == null || fTempPaths.length != nodes.length;
+               Thread extractor = null;
+               if (createTempFiles) {
+                       fTempPaths = new String[nodes.length];
+                       final File tmpDir = nodes[0].getModel().getTempDir();
+                       for (int i = 0; i < nodes.length; i++) {
+                               Node node = nodes[i];
+                               File file = new File(tmpDir, node.getFullPath());
+                               fTempPaths[i] = file.getAbsolutePath();
+                               if (node.isFolder())
+                                       file.mkdirs();
+                       }
+                       extractor = new Thread(new Runnable() {
+                               public void run() {
+                                       ExtractOperation extractOperation = new ExtractOperation();
+                                       extractOperation.extract(nodes, tmpDir, true, true, new NullProgressMonitor());
+                               }
+                       }, "Extractor"); //$NON-NLS-1$
+                       extractor.start();
+               }
+               if (extractor != null) {
+                       try {
+                               extractor.join();
+                       } catch (InterruptedException e) {
+                               e.printStackTrace();
+                       }
+               }
+               event.data = fTempPaths;
+       }
+
+       public void dragFinished(DragSourceEvent event) {
+               fTempPaths = null;
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/ZipEditorDropAdapter.java b/org.tizen.common.externals/src/zipeditor/ZipEditorDropAdapter.java
new file mode 100644 (file)
index 0000000..dfc4504
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.FileTransfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.ui.part.PluginDropAdapter;
+
+import zipeditor.model.Node;
+import zipeditor.operations.AddOperation;
+
+public class ZipEditorDropAdapter extends PluginDropAdapter {
+
+       public ZipEditorDropAdapter(StructuredViewer viewer) {
+               super(viewer);
+       }
+       
+       public void dragEnter(DropTargetEvent event) {
+               if (FileTransfer.getInstance().isSupportedType(event.currentDataType)
+                               && event.detail == DND.DROP_DEFAULT) {
+                       event.detail = DND.DROP_COPY;
+               }
+               super.dragEnter(event);
+       }
+
+       public boolean validateDrop(Object target, int operation, TransferData transferType) {
+        if (FileTransfer.getInstance().isSupportedType(transferType))
+                       return true;
+        return super.validateDrop(target, operation, transferType);
+       }
+
+       public boolean performDrop(Object data) {
+               if (!(data instanceof String[]))
+                       return false;
+               Node selectedNode = (Node) getCurrentTarget();
+               Node parentNode = selectedNode;
+               if (parentNode == null && getViewer().getInput() instanceof Node)
+                       parentNode = (Node) getViewer().getInput();
+               if (!parentNode.isFolder())
+                       parentNode = parentNode.getParent();
+               if (getViewer() instanceof TreeViewer && getCurrentLocation() == LOCATION_BEFORE
+                               && parentNode != getViewer().getInput())
+                       parentNode = parentNode.getParent();
+               String[] names = (String[]) data;
+               AddOperation operation = new AddOperation();
+               operation.execute(names, parentNode, selectedNode, (StructuredViewer) getViewer());
+               return true;
+       }
+
+}
diff --git a/org.tizen.common.externals/src/zipeditor/ZipEditorPlugin.java b/org.tizen.common.externals/src/zipeditor/ZipEditorPlugin.java
new file mode 100644 (file)
index 0000000..3f2d944
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+import zipeditor.model.Node;
+import zipeditor.model.ZipModel;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class ZipEditorPlugin extends AbstractUIPlugin {
+
+       // The plug-in ID
+       public static final String PLUGIN_ID = "org.tizen.common.externals"; //$NON-NLS-1$
+       
+       // The shared instance
+       private static ZipEditorPlugin plugin;
+
+       public final static boolean DEBUG = Boolean.valueOf(Platform.getDebugOption("ZipEditor/debug")).booleanValue(); //$NON-NLS-1$
+
+       private Map images;
+       
+       private Map fModelToFileNode = new HashMap();
+
+       /**
+        * The constructor
+        */
+       public ZipEditorPlugin() {
+               plugin = this;
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+        */
+       public void start(BundleContext context) throws Exception {
+               super.start(context);
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+        */
+       public void stop(BundleContext context) throws Exception {
+               plugin = null;
+               if (images != null) {
+                       for (Iterator it = images.values().iterator(); it.hasNext();) {
+                               ((Image) it.next()).dispose();
+                       }
+                       images.clear();
+                       images = null;
+               }
+               fModelToFileNode.clear();
+               fModelToFileNode = null;
+               super.stop(context);
+       }
+
+       /**
+        * Returns the shared instance
+        *
+        * @return the shared instance
+        */
+       public static ZipEditorPlugin getDefault() {
+           if ( plugin == null ) {
+               plugin = new ZipEditorPlugin();
+           }
+               return plugin;
+       }
+       
+       public void addFileMonitor(File file, Node node) {
+               Map fileToNode = (Map) fModelToFileNode.get(node.getModel());
+               if (fileToNode == null)
+                       fModelToFileNode.put(node.getModel(), fileToNode = new HashMap());
+               fileToNode.put(file, new Object[] { node, new Long(System.currentTimeMillis()) });
+       }
+       
+       public void removeFileMonitors(ZipModel model) {
+               Map fileToNode = (Map) fModelToFileNode.remove(model);
+               if (fileToNode != null)
+                       fileToNode.clear();
+       }
+
+       public void checkFilesForModification(ZipModel model) {
+               Map fileToNode = (Map) fModelToFileNode.get(model);
+               if (fileToNode == null)
+                       return;
+               for (Iterator it = fileToNode.keySet().iterator(); it.hasNext(); ) {
+                       File file = (File) it.next();
+                       Object[] value = (Object[]) fileToNode.get(file);
+                       long creationTime = ((Long) value[1]).longValue();
+                       if (file.lastModified() > creationTime) {
+                               value[1] = new Long(file.lastModified());
+                               indicateModification(fileToNode, file, (Node) value[0]);
+                       }
+               }
+       }
+
+       private void indicateModification(Map fileToNode, File file, Node node) {
+               if (MessageDialog.openQuestion(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+                               Messages.getString("ZipEditor.1"), Messages.getFormattedString("ZipEditor.0", //$NON-NLS-1$ //$NON-NLS-2$
+                                               new Object[] { file.getName(), node.getModel().getZipPath() != null
+                                                               ? node.getModel().getZipPath().getName() : "" }))) { //$NON-NLS-1$
+                       node.updateContent(file);
+               } else {
+                       node.reset();
+                       fileToNode.remove(file);
+               }
+       }
+
+       public static IStatus log(Object message) {
+               IStatus status = null;
+               Object debugMessage = message;
+               if (message instanceof IStatus) {
+                       status = (IStatus) message;
+                       debugMessage = ((IStatus) message).getMessage();
+               } else if (message instanceof Throwable) {
+                       status = createErrorStatus(((Throwable) message).getMessage(), (Throwable) message);
+               } else {
+                       status = createErrorStatus(message != null ? message.toString() : null, null);
+               }
+               plugin.getLog().log(status);
+               if (DEBUG) {
+                       if (debugMessage instanceof Throwable)
+                               ((Throwable) debugMessage).printStackTrace();
+                       else
+                               System.out.println(debugMessage);
+               }
+               return status;
+       }
+       
+       public static ImageDescriptor getImageDescriptor(String path) {
+               return imageDescriptorFromPlugin(PLUGIN_ID, path);
+       }
+
+       public static Image getImage(ImageDescriptor descriptor) {
+               return doGetImage(descriptor);
+       }
+
+       public static Image getImage(String path) {
+               return doGetImage(path);
+       }
+       
+       private static Image doGetImage(Object object) {
+               Map images = plugin.images;
+               if (images == null)
+                       images = plugin.images = new HashMap();
+               Image image = (Image) images.get(object);
+               if (image == null) {
+                       ImageDescriptor descriptor = object instanceof ImageDescriptor ? (ImageDescriptor) object : getImageDescriptor((String) object);
+                       image = descriptor != null ? descriptor.createImage() : ImageDescriptor.getMissingImageDescriptor().createImage();
+                       images.put(object, image);
+               }
+               return image;
+       }
+
+       public static IStatus createErrorStatus(String message, Throwable exception) {
+               return new Status(IStatus.ERROR, PLUGIN_ID, 0, message != null ? message : exception.toString(), exception);
+       }
+
+       private static IStatus[] createErrorStatuses(Throwable exception) {
+               StringWriter sw = new StringWriter();
+               if (exception != null)
+                       exception.printStackTrace(new PrintWriter(sw));
+               StringTokenizer st = new StringTokenizer(sw.toString(), "\r\n"); //$NON-NLS-1$
+               IStatus[] status = new IStatus[st.countTokens()];
+               for (int i = 0; i < status.length; i++) {
+                       status[i] = createErrorStatus(st.nextToken(), null);
+               }
+               return status;
+       }
+
+       public static void showErrorDialog(Shell shell, String message, Throwable exception, boolean logError) {
+               if (logError)
+                       log(exception);
+               ErrorDialog.openError(shell, Messages.getString("ZipEditor.8"), //$NON-NLS-1$
+                               message,
+                               new MultiStatus(PLUGIN_ID, 0, createErrorStatuses(exception),
+                                               Messages.getString("ZipEditorPlugin.0"), exception)); //$NON-NLS-1$
+       }
+
+       public static void showErrorDialog(Shell shell, String message, Throwable exception) {
+               showErrorDialog(shell, message, exception, true);
+       }
+
+}
diff --git a/org.tizen.common.externals/src/zipeditor/ZipLabelProvider.java b/org.tizen.common.externals/src/zipeditor/ZipLabelProvider.java
new file mode 100644 (file)
index 0000000..fc8d2bf
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import java.text.DateFormat;
+import java.text.NumberFormat;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.program.Program;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+import zipeditor.model.Node;
+import zipeditor.model.NodeProperty;
+import zipeditor.model.ZipNode;
+import zipeditor.model.ZipNodeProperty;
+
+public class ZipLabelProvider extends LabelProvider implements ITableLabelProvider {
+       protected static final DateFormat DATE_FORMAT = DateFormat.getDateTimeInstance();
+       protected static final NumberFormat NUMBER_FORMAT = NumberFormat.getNumberInstance();
+
+       private static Object TYPE_LABEL_KEY = new Object();
+       
+       public static String getTypeLabel(Node node) {
+               String label = (String) node.getProperty(TYPE_LABEL_KEY);
+               if (label == null)
+                       node.setProperty(TYPE_LABEL_KEY, label = doGetTypeLabel(node));
+               return label;
+       }
+       
+       private static String doGetTypeLabel(Node node) {
+               Program program = Program.findProgram(node.getType());
+               IContentType contentType = Platform.getContentTypeManager().findContentTypeFor(node.getName());
+               return node.isFolder() ? Messages.getString("ZipLabelProvider.1") //$NON-NLS-1$
+                               : contentType != null ? contentType.getName()
+                                               : program != null ? program.getName()
+                                                               : node.getType() != null && node.getType().length() > 0 ?
+                                                                               Messages.getFormattedString("ZipLabelProvider.2", node.getType()) //$NON-NLS-1$
+                                                                               : Messages.getString("ZipLabelProvider.0"); //$NON-NLS-1$
+       }
+
+       private int[] fOrder;
+
+       public String getText(Object element) {
+           if ( element instanceof IResource ) {
+               return ((IResource) element).getName();
+           }
+               return element instanceof Node ? getNodeText((Node) element) : super
+                               .getText(element);
+       }
+       
+       private String getNodeText(Node node) {
+               String prefix = node.isAdded() ? "*" : node.isModified() ? ">" : new String(); //$NON-NLS-1$ //$NON-NLS-2$
+               return prefix + node.getName();
+       }
+
+       public Image getImage(Object element) {
+               if (element instanceof Node) {
+                       Node node = (Node) element;
+                       if (node.isFolder())
+                               return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER);
+                       
+                       ImageDescriptor descriptor = PlatformUI.getWorkbench().getEditorRegistry().getImageDescriptor(node.getName());
+                       if (descriptor != null)
+                               return ZipEditorPlugin.getImage(descriptor);
+                       return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE);
+               }
+               return super.getImage(element);
+       }
+
+       public Image getColumnImage(Object element, int columnIndex) {
+               if (fOrder == null)
+                       fOrder = initializeOrder();if (fOrder.length == 0)
+                               return null;
+               switch (fOrder[columnIndex]) {
+               default:
+                       return null;
+               case NodeProperty.NAME:
+                       return getImage(element);
+               }
+       }
+       
+       public String getColumnText(Object element, int columnIndex) {
+               if (!(element instanceof Node))
+                       return new String();
+               if (fOrder == null)
+                       fOrder = initializeOrder();
+               if (fOrder.length == 0)
+                       return new String();
+               Node node = (Node) element;
+               switch (fOrder[columnIndex]) {
+               default:
+                       return getText(element);
+               case NodeProperty.NAME:
+                       return getNodeText(node);
+               case NodeProperty.TYPE:
+                       return getTypeLabel(node);
+               case NodeProperty.DATE:
+                       return formatDate(node.getTime());
+               case NodeProperty.SIZE:
+                       return formatLong(node.getSize());
+               case ZipNodeProperty.PACKED_SIZE:
+                       return formatLong(node instanceof ZipNode ? ((ZipNode) node).getCompressedSize() : 0);
+               case NodeProperty.PATH:
+                       return node.getPath();
+               case ZipNodeProperty.ATTR:
+                       return new String(node instanceof ZipNode ? ((ZipNode) node).getExtra() : new byte[0]);
+               case ZipNodeProperty.CRC:
+                       return Long.toHexString(node instanceof ZipNode ? ((ZipNode) node).getCrc() : 0);
+               case ZipNodeProperty.RATIO:
+                       return formatLong(Math.max(Math.round(node instanceof ZipNode ? ((ZipNode) node).getRatio() : 0), 0)) + "%"; //$NON-NLS-1$
+               }
+       }
+
+       private int[] initializeOrder() {
+               IPreferenceStore store = ZipEditorPlugin.getDefault().getPreferenceStore();
+               int[] values = (int[]) PreferenceInitializer.split(store.getString(PreferenceConstants.VISIBLE_COLUMNS), PreferenceConstants.COLUMNS_SEPARATOR, int.class);
+               return values;
+       }
+
+       protected static String formatDate(long time) {
+               return time != -1 ? DATE_FORMAT.format(new Long(time)) : new String();
+       }
+
+       protected static String formatLong(long value) {
+               return NUMBER_FORMAT.format(value);
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/ZipNodePropertyPage.java b/org.tizen.common.externals/src/zipeditor/ZipNodePropertyPage.java
new file mode 100644 (file)
index 0000000..c838524
--- /dev/null
@@ -0,0 +1,71 @@
+package zipeditor;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbenchPropertyPage;
+
+import zipeditor.model.Node;
+import zipeditor.model.ZipNode;
+import zipeditor.model.ZipNodeProperty;
+
+public class ZipNodePropertyPage extends NodePropertyPage implements IWorkbenchPropertyPage {
+       private Text fAttributes;
+       private Text fPackedSize;
+       private Text fRatio;
+       private Text fCrc;
+       private Text fComment;
+       
+       protected Control createContents(Composite parent) {
+               
+               Composite control = (Composite) createPropertiesSection(parent);
+
+               createLabel(control, ZipNodeProperty.PPACKED_SIZE.toString(), 1);
+               fPackedSize = createText(control, 30, 1, false);
+               setFieldText(fPackedSize, new NodePropertyAccessor() {
+                       public Object getSinglePropertyValue(Node node) {
+                               return new Long(((ZipNode) node).getCompressedSize());
+                       }
+               }, true);
+               createLabel(control, ZipNodeProperty.PRATIO.toString(), 1);
+               fRatio = createText(control, 30, 1, false);
+               setFieldText(fRatio, new PropertyAccessor() {
+                       public Object getPropertyValue(Object object) {
+                               return formatLong(Math.max(Math.round(((ZipNode) object).getRatio()), 0)) + "%"; //$NON-NLS-1$
+                       }
+               });
+               createLabel(control, ZipNodeProperty.PCRC.toString(), 1);
+               fCrc = createText(control, 30, 1, false);
+               setFieldText(fCrc, new PropertyAccessor() {
+                       public Object getPropertyValue(Object object) {
+                               return Long.toHexString(((ZipNode) object).getCrc()).toUpperCase();
+                       }
+               });
+               createLabel(control, ZipNodeProperty.PATTR.toString(), 1);
+               fAttributes = createText(control, 30, 1, false);
+               setFieldText(fAttributes, new PropertyAccessor() {
+                       public Object getPropertyValue(Object object) {
+                               return new String(((ZipNode) object).getExtra());
+                       }
+               });
+               createLabel(control, ZipNodeProperty.PCOMMENT.toString(), 1);
+               fComment = createText(control, 30, 1, true);
+               setFieldText(fComment, new MultiplePropertyAccessor(ZipNode.class).getAccessor("comment")); //$NON-NLS-1$
+               
+               applyDialogFont(control);
+               return control;
+       }
+
+       public boolean performOk() {
+               boolean ok = super.performOk();
+               if (!ok)
+                       return false;
+               Node[] nodes = getNodes();
+               String comment = fComment.getText();
+               for (int i = 0; i < nodes.length; i++) {
+                       if (!nonEqualStringLabel.equals(comment))
+                               ((ZipNode) nodes[i]).setComment(comment.length() > 0 ? comment : null);
+               }
+               return true;
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/ZipOutlinePage.java b/org.tizen.common.externals/src/zipeditor/ZipOutlinePage.java
new file mode 100644 (file)
index 0000000..84df83d
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IContributionManager;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.FileTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
+
+import zipeditor.ZipEditor.NodeComparer;
+import zipeditor.actions.AddAction;
+import zipeditor.actions.CollapseAllAction;
+import zipeditor.actions.DeleteAction;
+import zipeditor.actions.ExtractAction;
+import zipeditor.actions.MultiPropertyDialogAction;
+import zipeditor.actions.NewFolderAction;
+import zipeditor.actions.RenameNodeAction;
+import zipeditor.actions.SelectAllAction;
+import zipeditor.actions.SortAction;
+import zipeditor.actions.ViewerAction;
+import zipeditor.model.Node;
+
+public class ZipOutlinePage extends ContentOutlinePage {
+       private class LinkAction extends Action  {
+               public LinkAction() {
+                       super(Messages.getString("ZipOutlinePage.0")); //$NON-NLS-1$
+                       setToolTipText(Messages.getString("ZipOutlinePage.1")); //$NON-NLS-1$
+                       setImageDescriptor(ZipEditorPlugin.getImageDescriptor("icons/synced.gif")); //$NON-NLS-1$
+                       setChecked(ZipEditorPlugin.getDefault().getPreferenceStore().getBoolean(PREFERENCE_LINKED));
+               }
+               
+               public void run() {
+                       boolean checked = isChecked();
+                       ZipEditorPlugin.getDefault().getPreferenceStore().setValue(PREFERENCE_LINKED, checked);
+                       IEditorPart editor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
+                       if (editor instanceof ZipEditor) {
+                               Node[] nodes = ((ZipEditor) editor).getSelectedNodes();
+                               if (nodes.length == 1)
+                               setSelection(new StructuredSelection(nodes[0]));
+                       }
+               }
+       };
+
+       private final static String PREFERENCE_LINKED = "outline_linked"; //$NON-NLS-1$
+
+       private AddAction fAddAction;
+       private ViewerAction fExtractAction;
+       private ViewerAction fDeleteAction;
+       private IAction fPropertiesAction;
+       private SelectAllAction fSelectAllAction;
+       private NewFolderAction fNewFolderAction;
+       private RenameNodeAction fRenameNodeAction;
+
+       public void createControl(Composite parent) {
+               super.createControl(parent);
+               getTreeViewer().setContentProvider(new ZipContentProvider(PreferenceConstants.VIEW_MODE_TREE));
+               getTreeViewer().setLabelProvider(new ZipLabelProvider());
+               getTreeViewer().setSorter(new ZipSorter(PreferenceConstants.PREFIX_OUTLINE));
+               getTreeViewer().setComparer(new NodeComparer());
+
+               createActions();
+               MenuManager manager = new MenuManager();
+               manager.setRemoveAllWhenShown(true);
+               manager.addMenuListener(new IMenuListener() {
+                       public void menuAboutToShow(IMenuManager manager) {
+                               contextMenuAboutToShow(manager);
+                       }
+               });
+               Menu contextMenu = manager.createContextMenu(getTreeViewer().getControl());
+               getTreeViewer().getControl().setMenu(contextMenu);
+
+               initDragAndDrop(getTreeViewer());
+       }
+
+       private void createActions() {
+               fAddAction = new AddAction(getTreeViewer());
+               fExtractAction = new ExtractAction(getTreeViewer());
+               fDeleteAction = new DeleteAction(getTreeViewer());
+               fSelectAllAction = new SelectAllAction(getTreeViewer());
+               fPropertiesAction = new MultiPropertyDialogAction(getSite(), getTreeViewer());
+               fNewFolderAction = new NewFolderAction(getTreeViewer());
+               fRenameNodeAction = new RenameNodeAction(getTreeViewer());
+
+               updateActions();
+       }
+
+       private void updateActions() {
+               boolean empty = getSelection().isEmpty();
+               fDeleteAction.setEnabled(!empty);
+               fPropertiesAction.setEnabled(!empty);
+               getSite().getActionBars().setGlobalActionHandler(ActionFactory.DELETE.getId(), fDeleteAction);
+               getSite().getActionBars().setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), fSelectAllAction);
+               getSite().getActionBars().setGlobalActionHandler(ActionFactory.PROPERTIES.getId(), fPropertiesAction);
+               getSite().getActionBars().setGlobalActionHandler(ActionFactory.RENAME.getId(), fRenameNodeAction);
+       }
+
+       private void initDragAndDrop(StructuredViewer viewer) {
+               int ops = DND.DROP_DEFAULT | DND.DROP_COPY;
+               Transfer[] transfers = new Transfer[] { FileTransfer.getInstance() };
+
+        viewer.addDragSupport(ops, transfers, new ZipEditorDragAdapter(this));
+        viewer.addDropSupport(ops | DND.DROP_DEFAULT, transfers, new ZipEditorDropAdapter(viewer));
+       }
+       
+       private void contextMenuAboutToShow(IContributionManager manager) {
+               manager.add(fNewFolderAction);
+               manager.add(new Separator());
+               manager.add(fAddAction);
+               manager.add(fExtractAction);
+               manager.add(new Separator());
+               manager.add(fDeleteAction);
+               manager.add(new Separator());
+               manager.add(fPropertiesAction);
+       }
+
+       public void makeContributions(IMenuManager menuManager, IToolBarManager toolBarManager,
+                       IStatusLineManager statusLineManager) {
+               toolBarManager.add(new SortAction(getTreeViewer(), PreferenceConstants.PREFIX_OUTLINE));
+               toolBarManager.add(new Separator());
+               toolBarManager.add(new CollapseAllAction(getTreeViewer()));
+               toolBarManager.add(new LinkAction());
+       }
+       
+       public void selectionChanged(SelectionChangedEvent event) {
+               super.selectionChanged(event);
+               updateActions();
+       }
+
+       public void setFocus() {
+               super.setFocus();
+               updateActions();
+       }
+
+       public void setInput(final Node node) {
+               if (getTreeViewer() == null || getTreeViewer().getControl().isDisposed())
+                       return;
+               if (Utils.isUIThread())
+                       getTreeViewer().setInput(node);
+               else {
+                       getTreeViewer().getControl().getDisplay().syncExec(new Runnable() {
+                               public void run() {
+                                       getTreeViewer().setInput(node);
+                               }
+                       });
+               }
+       }
+
+       public Object getInput() {
+               return getTreeViewer().getInput();
+       }
+
+       public void refresh() {
+               if (getTreeViewer() == null || getTreeViewer().getControl().isDisposed())
+                       return;
+               getTreeViewer().getControl().setRedraw(false);
+               getTreeViewer().refresh();              
+               getTreeViewer().getControl().setRedraw(true);
+       }
+
+       public boolean isLinkingEnabled() {
+               return ZipEditorPlugin.getDefault().getPreferenceStore().getBoolean(PREFERENCE_LINKED);
+       }
+
+}
diff --git a/org.tizen.common.externals/src/zipeditor/ZipSorter.java b/org.tizen.common.externals/src/zipeditor/ZipSorter.java
new file mode 100644 (file)
index 0000000..92a13a5
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+
+import zipeditor.model.Node;
+import zipeditor.model.NodeProperty;
+import zipeditor.model.ZipNode;
+import zipeditor.model.ZipNodeProperty;
+
+public class ZipSorter extends ViewerSorter {
+       private int fSortBy;
+       private int fSortDirection;
+       private boolean fSortEnabled;
+       private int fMode;
+       private String fPreferencePrefix;
+       
+       public ZipSorter() {
+               this(PreferenceConstants.PREFIX_NAVIGATOR);
+       }
+       
+       public ZipSorter(String preferencePrefix) {
+               fPreferencePrefix = preferencePrefix;
+               update(); 
+       }
+
+       public int compare(Viewer viewer, Object e1, Object e2) {
+               if (!fSortEnabled)
+                       return 0;
+               if (e1 instanceof Node && e2 instanceof Node) {
+                       return compareNodes((Node) e1, (Node) e2);
+               }
+               return super.compare(viewer, e1, e2);
+       }
+       
+       private int compareNodes(Node z1, Node z2) {
+               boolean ascending = fSortDirection == SWT.UP;
+               if ((fMode & PreferenceConstants.VIEW_MODE_TREE) > 0)
+                       return compareByNames(z1, z2, true);
+                       
+               switch (fSortBy) {
+               default:
+                       return 0;
+               case NodeProperty.NAME:
+                       return compareByNames(z1, z2, ascending);
+               case NodeProperty.TYPE:
+                       return compare(ZipLabelProvider.getTypeLabel(z1), ZipLabelProvider.getTypeLabel(z2), ascending);
+               case NodeProperty.DATE:
+                       return compare(z1.getTime(), z2.getTime(), ascending);
+               case NodeProperty.SIZE:
+                       return compare(z1.getSize(), z2.getSize(), ascending);
+               case ZipNodeProperty.RATIO:
+                       return z1 instanceof ZipNode && z2 instanceof ZipNode ? compare(Math.round(((ZipNode) z1).getRatio()), Math.round(((ZipNode) z2).getRatio()), ascending) : 0;
+               case ZipNodeProperty.PACKED_SIZE:
+                       return z1 instanceof ZipNode && z2 instanceof ZipNode ? compare(((ZipNode) z1).getCompressedSize(), ((ZipNode) z2).getCompressedSize(), ascending) : 0;
+               case ZipNodeProperty.CRC:
+                       return z1 instanceof ZipNode && z2 instanceof ZipNode ? compare(((ZipNode) z1).getCrc(), ((ZipNode) z2).getCrc(), ascending) : 0;
+               case ZipNodeProperty.ATTR:
+                       return 0;
+               case NodeProperty.PATH:
+                       return compare(z1.getPath(), z2.getPath(), ascending);
+               }
+       }
+       
+       private int compareByNames(Node z1, Node z2, boolean ascending) {
+               if (z1.isFolder() && !z2.isFolder())
+                       return ascending ? -1 : 1;
+               if (z2.isFolder() && !z1.isFolder())
+                       return ascending ? 1 : -1;
+               return compare(z1.getName(), z2.getName(), ascending);
+       }
+
+       private int compare(String s1, String s2, boolean ascending) {
+               return ascending ? s1.compareToIgnoreCase(s2) : s2.compareToIgnoreCase(s1);
+       }
+
+       private int compare(long l1, long l2, boolean ascending) {
+               if (l1 == l2)
+                       return 0;
+               return l1 < l2 ? ascending ? -1 : 1 : ascending ? 1 : -1;
+       }
+
+       public void update() {
+               IPreferenceStore store = ZipEditorPlugin.getDefault().getPreferenceStore();
+               fSortBy = store.getInt(PreferenceConstants.SORT_BY);
+               fSortDirection = store.getInt(PreferenceConstants.SORT_DIRECTION);
+               fSortEnabled = store.getBoolean(fPreferencePrefix + PreferenceConstants.SORT_ENABLED);
+               fMode = store.getInt(fPreferencePrefix + PreferenceConstants.VIEW_MODE);
+       }
+       
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/ActionMessages.java b/org.tizen.common.externals/src/zipeditor/actions/ActionMessages.java
new file mode 100644 (file)
index 0000000..7b3676b
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class ActionMessages {
+       private static final String BUNDLE_NAME = "zipeditor.actions.ActionMessages"; //$NON-NLS-1$
+
+       private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+                       .getBundle(BUNDLE_NAME);
+
+       private ActionMessages() {
+       }
+
+       public static String getString(String key) {
+               try {
+                       return RESOURCE_BUNDLE.getString(key);
+               } catch (MissingResourceException e) {
+                       return '!' + key + '!';
+               }
+       }
+
+       public static String getFormattedString(String key, Object argument) {
+               try {
+                       String pattern = RESOURCE_BUNDLE.getString(key);
+                       return MessageFormat.format(pattern, argument instanceof Object[] ? (Object[]) argument : new Object[] { argument });
+               } catch (MissingResourceException e) {
+                       return '!' + key + '!';
+               }
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/ActionMessages.properties b/org.tizen.common.externals/src/zipeditor/actions/ActionMessages.properties
new file mode 100644 (file)
index 0000000..f30aea8
--- /dev/null
@@ -0,0 +1,72 @@
+CollapseAllAction.0=Collapse All
+CollapseAllAction.1=Collapse all elements
+ReverseSelectionAction_0=Reverse Selection
+RevertAction.0=Re&vert
+ToggleViewModeAction.0=ToggleViewMode
+ToggleViewModeAction.1=Toggle the view between tree and table
+ExtractAction.0=E&xtract...
+ExtractAction.1=Extract files from the archive
+ExtractAction.2=Select a target to extract to
+ExtractAction.3=Refresh workspace
+SortAction.0=S&ort
+SortAction.1=Sort the entries
+OpenAction.0=&Open
+OpenAction.1=View file inside the archive
+OpenWithMenu.0=Error
+OpenWithMenu.1=&Default Editor
+OpenWithMenu.10=E&xternal
+OpenWithMenu.11=&Internal
+OpenWithMenu.12=&Edit
+OpenWithMenu.13=Remove
+OpenWithMenu.14=&Label:
+OpenWithMenu.15=&Command:
+OpenWithMenu.16=Edit external program
+OpenWithMenu.17=| pipe symbol\n$z zip file path\n$p path of the temporary file for the zip entry\n$n zip entry name without extension\n$f zip entry name with extension\n$i internal text editor\n$e <editorId>\n$x appends the given file extension to the temporary file
+OpenWithMenu.18=&Add
+OpenWithMenu.19=&Browse
+OpenWithMenu.2=Problems Opening Editor
+OpenWithMenu.4=&Other...
+OpenWithMenu.5=Open with
+OpenWithMenu.6=Choose the program to open the file:
+OpenWithMenu.7=File: 
+OpenWithMenu.8=&Previously chosen editor
+OpenWithMenu.9=&Add
+DeleteAction.0=&Delete
+DeleteAction.1=Delete the selected entries from the archive
+SelectAllAction.0=Select all
+SelectPatternAction.0=Select Pattern
+SelectPatternAction.1=Select Pattern
+SelectPatternAction.2=Choose a pattern to select (* and ? are wildcards)
+AddAction.0=&Add...
+AddAction.1=Add files to the archive
+AddAction.2=Select files to add to the archive
+DialogAction.0=Select resources from &workspace:
+DialogAction.1=Select files from &file system:
+DialogAction.2={0} resources from workspace and {1} from the file system are selected.
+DialogAction.3=<comma separated patterns> *,? as wildcards
+OpenActionGroup.0=Open Wit&h
+SaveAction.0=&Save
+PreferencesAction.0=Preferences...
+PreferencesAction.1=Modify the preferences
+PreferencesAction.2=Visible Columns
+PreferencesAction.3=Folders
+PreferencesAction.4=Visible
+PreferencesAction.5=All in one layer
+PreferencesAction.6=Archive folders as separate entries
+DeferredMenuManager.0=Creating menu
+DeferredMenuManager.1=Pending...
+NewFolderAction.0=New &Folder...
+NewFolderAction.1=New Folder
+NewFolderAction.2=Please provide the new folder name:
+FileOpener.0=Error executing external program
+FileOpener.1=The file could not be opened using the external program
+RenameNodeAction.0=Rename
+RenameNodeAction.1=Rename the entry
+RenameNodeAction.2=The entry {0} already exists. Should it be renamed regardlessly?
+RenameNodeAction.3=Entry exists
+CopyAction.0=&Copy
+CopyAction.1=Copy the name of the node
+CopyAction.2=Copy &Qualified Name
+CopyAction.3=Copy the path of the node
+MostRecentlyUsedMenu.0=Extract and open file
+MostRecentlyUsedMenu.1=Extracting...
diff --git a/org.tizen.common.externals/src/zipeditor/actions/AddAction.java b/org.tizen.common.externals/src/zipeditor/actions/AddAction.java
new file mode 100644 (file)
index 0000000..3cd8672
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import org.eclipse.jface.viewers.StructuredViewer;
+
+import zipeditor.ZipEditorPlugin;
+import zipeditor.model.Node;
+import zipeditor.operations.AddOperation;
+
+public class AddAction extends DialogAction {
+       public AddAction(StructuredViewer viewer) {
+               super(ActionMessages.getString("AddAction.0"), viewer, true); //$NON-NLS-1$
+               setToolTipText(ActionMessages.getString("AddAction.1")); //$NON-NLS-1$
+               setImageDescriptor(ZipEditorPlugin.getImageDescriptor("icons/add.gif")); //$NON-NLS-1$
+       }
+
+       public void run() {
+               String[] paths = openDialog(ActionMessages.getString("AddAction.2"), null, true, true); //$NON-NLS-1$);
+               if (paths == null || paths.length == 0)
+                       return;
+               Node[] selectedNodes = getSelectedNodes();
+               Node targetNode = selectedNodes.length > 0 ? selectedNodes[0] : getViewerInputAsNode();
+               AddOperation operation = new AddOperation();
+               operation.execute(paths, targetNode, null, getViewer());
+       }
+
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/CollapseAllAction.java b/org.tizen.common.externals/src/zipeditor/actions/CollapseAllAction.java
new file mode 100644 (file)
index 0000000..2d3f87f
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+
+import zipeditor.ZipEditorPlugin;
+
+
+public class CollapseAllAction extends ViewerAction {
+       public CollapseAllAction(StructuredViewer viewer) {
+               super(ActionMessages.getString("CollapseAllAction.0"), viewer); //$NON-NLS-1$
+               setToolTipText(ActionMessages.getString("CollapseAllAction.1")); //$NON-NLS-1$
+               setImageDescriptor(ZipEditorPlugin.getImageDescriptor("icons/collapseall.gif")); //$NON-NLS-1$
+       }
+
+       public void run() {
+               if (getViewer() instanceof TreeViewer)
+                       ((TreeViewer) getViewer()).collapseAll();
+       }
+
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/CopyAction.java b/org.tizen.common.externals/src/zipeditor/actions/CopyAction.java
new file mode 100644 (file)
index 0000000..e5ede1c
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * (c) Copyright 2002, 2010 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+import zipeditor.ZipEditorPlugin;
+import zipeditor.model.Node;
+
+public class CopyAction extends ViewerAction {
+       private boolean fFullyQualified;
+       private String fLineSeparator = System.getProperty("line.separator"); //$NON-NLS-1$
+       private Clipboard fClipboard;
+
+       public CopyAction(StructuredViewer viewer, boolean fullyQualified, Clipboard clipboard) {
+               super(ActionMessages.getString(fullyQualified ? "CopyAction.2" : "CopyAction.0"), viewer); //$NON-NLS-1$ //$NON-NLS-2$
+               setToolTipText(ActionMessages.getString(fullyQualified ? "CopyAction.3" : "CopyAction.1")); //$NON-NLS-1$ //$NON-NLS-2$
+               setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(
+                               ISharedImages.IMG_TOOL_COPY));
+               fFullyQualified = fullyQualified;
+               fClipboard = clipboard;
+       }
+
+       public void run() {
+               Node[] nodes = getSelectedNodes();
+               StringBuilder text = new StringBuilder();
+               for (int i = 0; i < nodes.length; i++) {
+                       if (i > 0)
+                               text.append(fLineSeparator);
+                       text.append(fFullyQualified ? nodes[i].getPath() + nodes[i].getName(): nodes[i].getName());
+               }
+               if (text.length() > 0) {
+                       try {
+                               fClipboard.setContents(
+                                       new Object[] { text.toString() },
+                                       new Transfer[] { TextTransfer.getInstance() });
+                       } catch (SWTError e) {
+                               ZipEditorPlugin.showErrorDialog(
+                                               getViewer().getControl().getShell(),
+                                               ActionMessages.getString("CopyAction.2"), e); //$NON-NLS-1$
+                       }
+               }
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/DeferredMenuManager.java b/org.tizen.common.externals/src/zipeditor/actions/DeferredMenuManager.java
new file mode 100644 (file)
index 0000000..f102021
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.IContributionManager;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.swt.widgets.Display;
+
+public class DeferredMenuManager extends MenuManager {
+       public static abstract class MenuJob extends Job {
+               private DeferredMenuManager fMenuManager;
+               protected Object fFamily;
+               protected Object fProperty;
+               public MenuJob(Object family, Object propertyValue) {
+                       super(ActionMessages.getString("DeferredMenuManager.0")); //$NON-NLS-1$
+                       Assert.isNotNull(family);
+                       fFamily = family;
+                       fProperty = propertyValue;
+               }
+               
+               protected abstract IStatus addToMenu(IProgressMonitor monitor, IMenuManager menu);
+               
+               protected IStatus run(IProgressMonitor monitor) {
+                       Assert.isNotNull(fMenuManager);
+                       addToMenu(monitor, fMenuManager);
+                       fMenuManager.finish();
+                       return Status.OK_STATUS;
+               }
+               
+               public boolean belongsTo(Object family) {
+                       return fFamily.equals(family);
+               }
+       };
+       
+       private final static QualifiedName ID_PROPERTY_NAME = new QualifiedName(DeferredMenuManager.class.getName(), "type"); //$NON-NLS-1$
+       private final static QualifiedName MENU_PROPERTY_NAME = new QualifiedName(DeferredMenuManager.class.getName(), "menu"); //$NON-NLS-1$
+       private static int useCount;
+
+       private Action fPendingAction = new Action(ActionMessages.getString("DeferredMenuManager.1")) {}; //$NON-NLS-1$
+       private int fCreateCount;
+
+       public DeferredMenuManager(IContributionManager parent, String text, String id) {
+               super(text, id);
+               fCreateCount = useCount;
+               setParent(parent);
+               fPendingAction.setId(getPendingId());
+               super.add(fPendingAction);
+       }
+       
+       public void add(IAction action) {
+               removePendingAction();
+               super.add(action);
+       }
+       
+       private void removePendingAction() {
+               Display.getDefault().syncExec(new Runnable() {
+                       public void run() {
+                               remove(getPendingId());
+                       }
+               });
+       }
+       
+       public String getPendingId() {
+               return fPendingAction.getClass().getName() + fPendingAction.hashCode();
+       }
+
+       public synchronized void finish() {
+               Display.getDefault().asyncExec(new Runnable() {
+                       public void run() {
+                               IContributionItem[] items = getItems();
+                               if (items.length == 1 && getPendingId().equals(items[0].getId())) {
+                                       dispose();
+                                       removeAll();
+                                       getParent().remove(DeferredMenuManager.this);
+                               } else {
+                                       remove(getPendingId());
+                                       update(false);
+                               }
+                       }
+               });
+       }
+
+       public static void addToMenu(IMenuManager parentMenu, String parentId, String menuText, String menuId, MenuJob job) {
+               Assert.isNotNull(parentMenu);
+               Assert.isNotNull(job);
+               DeferredMenuManager menuFromRunningJob = getMenuFromRunningJob(job.fFamily, job.fProperty); 
+               DeferredMenuManager subMenu = menuFromRunningJob != null ?
+                               menuFromRunningJob : new DeferredMenuManager(parentMenu, menuText, menuId);
+               if (menuFromRunningJob == null) {
+                       job.setSystem(true);
+                       job.setProperty(ID_PROPERTY_NAME, job.fProperty);
+                       job.setProperty(MENU_PROPERTY_NAME, subMenu);
+                       job.fMenuManager = subMenu;
+                       job.schedule();
+               } else {
+                       useCount++;
+               }
+               if (parentId != null && parentMenu.find(parentId) != null)
+                       parentMenu.appendToGroup(parentId, subMenu);
+               else
+                       parentMenu.add(subMenu);
+       }
+       
+       public boolean isVisible() {
+               if (useCount == fCreateCount)
+                       return super.isVisible();
+               // this adds the pending action again because this item
+               // has been removed in the update implementation of the super class
+               if (getItems().length == 0)
+                       super.add(fPendingAction);
+               return true;
+       }
+       
+       public static boolean isRunning(Object jobFamily, Object propertyValue) {
+               return getMenuFromRunningJob(jobFamily, propertyValue) != null;
+       }
+
+       private static DeferredMenuManager getMenuFromRunningJob(Object jobFamily, Object propertyValue) {
+               Job[] jobs = Platform.getJobManager().find(jobFamily);
+               DeferredMenuManager menuFromRunningJob = null;
+               for (int i = 0; i < jobs.length; i++) {
+                       Object property = jobs[i].getProperty(ID_PROPERTY_NAME);
+                       if (property == propertyValue || property != null && property.equals(propertyValue)) {
+                               menuFromRunningJob = (DeferredMenuManager) jobs[i].getProperty(MENU_PROPERTY_NAME);
+                       }
+               }
+               return menuFromRunningJob;
+       }
+
+}
\ No newline at end of file
diff --git a/org.tizen.common.externals/src/zipeditor/actions/DeleteAction.java b/org.tizen.common.externals/src/zipeditor/actions/DeleteAction.java
new file mode 100644 (file)
index 0000000..c5273f3
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+import zipeditor.model.Node;
+
+public class DeleteAction extends ViewerAction {
+       public DeleteAction(StructuredViewer viewer) {
+               super(ActionMessages.getString("DeleteAction.0"), viewer); //$NON-NLS-1$
+               setToolTipText(ActionMessages.getString("DeleteAction.1")); //$NON-NLS-1$
+               setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(
+                               ISharedImages.IMG_TOOL_DELETE));
+       }
+
+       public void run() {
+               Node[] nodes = getSelectedNodes();
+               for (int i = 0; i < nodes.length; i++) {
+                       nodes[i].getParent().remove(nodes[i]);
+               }
+               if (nodes.length > 0) {
+                       refreshViewer();
+               }
+       }
+
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/DialogAction.java b/org.tizen.common.externals/src/zipeditor/actions/DialogAction.java
new file mode 100644 (file)
index 0000000..4b84e58
--- /dev/null
@@ -0,0 +1,420 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.model.WorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+import org.eclipse.ui.progress.UIJob;
+import org.eclipse.ui.views.navigator.ResourceSorter;
+
+import zipeditor.ZipEditorPlugin;
+
+
+public abstract class DialogAction extends ViewerAction {
+       private class FileSystemContentProvider implements ITreeContentProvider {
+               public Object[] getChildren(Object parentElement) {
+                       if (parentElement instanceof File[])
+                               return (Object[]) parentElement;
+                       else if (parentElement instanceof File) {
+                               File file = (File) parentElement;
+                               if (file.isDirectory()) {
+                                       File[] files = file.listFiles();
+                                       if (files != null)
+                                               return files;
+                               }
+                       }
+                       return new Object[0];
+               }
+
+               public boolean hasChildren(Object element) {
+                       return getChildren(element).length > 0;
+               }
+               
+               public Object[] getElements(Object inputElement) {
+                       return getChildren(inputElement);
+               }
+               
+               public Object getParent(Object element) {
+                       return element instanceof File ? ((File) element).getParentFile() : null;
+               }
+
+               public void dispose() {
+               }
+
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+               }
+       };
+       private class FileSystemLabelProvider extends LabelProvider {
+               public String getText(Object element) {
+                       if (element instanceof File) {
+                               File file = (File) element;
+                               return file.getName().length() > 0 ? file.getName() : file.getPath();
+                       }
+                       return super.getText(element);
+               }
+               
+               public Image getImage(Object element) {
+                       if (element instanceof File) {
+                               File file = (File) element;
+                               if (file.isDirectory())
+                                       return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER);
+                               ImageDescriptor descriptor = PlatformUI.getWorkbench().getEditorRegistry().getImageDescriptor(file.getName(), null);
+                               if (descriptor != null)
+                                       return ZipEditorPlugin.getImage(descriptor);
+                               return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE);
+                       }
+
+                       return super.getImage(element);
+               }
+       };
+       
+       private class FileSorter extends ViewerSorter {
+               public int category(Object element) {
+                       return ((File) element).isDirectory() ? -1 : 1;
+               }
+       };
+       
+       private class FileFilter extends ViewerFilter {
+               public boolean select(Viewer viewer, Object parentElement, Object element) {
+                       return element instanceof IFolder || element instanceof IProject ||
+                                       element instanceof File && ((File) element).isDirectory();
+               }
+       };
+       
+       private class FileDialog extends Dialog implements ISelectionChangedListener {
+               private class FilterArea extends Composite implements FocusListener, ModifyListener {
+                       private class RefreshJob extends UIJob {
+                               public RefreshJob(Display display) {
+                                       super(display, "Refresh"); //$NON-NLS-1$
+                               }
+
+                               public IStatus runInUIThread(IProgressMonitor monitor) {
+                                       if (!fText.isDisposed()) {
+                                               setPattern(fText.getText());
+                                               selectMatches();
+                                       }
+                                       return Status.OK_STATUS;
+                               }
+                       }
+
+                       private TreeViewer fViewer;
+                       private Color fGrayColor;
+                       private final String fEmptyText = ActionMessages.getString("DialogAction.3"); //$NON-NLS-1$
+                       private final Text fText;
+            private StringMatcher[] fMatchers;
+                       private final RefreshJob fRefreshJob = new RefreshJob(getDisplay());
+
+                       public FilterArea(Composite parent, String labelText) {
+                               super(parent, SWT.NONE);
+                               setLayout(new GridLayout(2, false));
+                               setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+                               Label label = new Label(this, SWT.LEFT);
+                               label.setText(labelText);
+                               fText = new Text(this, SWT.LEFT | SWT.BORDER);
+                               fText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+                               fText.setText(fEmptyText);
+                               fText.setForeground(getGrayColor());
+                               fText.addFocusListener(this);
+                               fText.addModifyListener(this);
+                       }
+
+                       private void setPattern(String patternString) {
+                               if (patternString == null || patternString.trim().length() == 0 || fEmptyText.equals(patternString)) {
+                                       fMatchers = null;
+                               }
+                               else {
+                                       String[] strings = patternString.split(","); //$NON-NLS-1$
+                                       fMatchers = new StringMatcher[strings.length];
+                                       for (int i = 0; i < strings.length; i++) {
+                                               fMatchers[i] = new StringMatcher(strings[i].trim(), true, false);
+                                       }
+                               }
+                       }
+
+                       private Color getGrayColor() {
+                               if (fGrayColor == null)
+                                       fGrayColor = new Color(getDisplay(), 160, 160, 160);
+                               return fGrayColor;
+                       }
+                       
+                       public void dispose() {
+                               fGrayColor.dispose();
+                               super.dispose();
+                       }
+
+                       public void focusLost(FocusEvent e) {
+                               if (fText.getText().length() == 0 || fEmptyText.equals(fText.getText())) {
+                                       fText.setForeground(getGrayColor());
+                                       fText.setText(fEmptyText);
+                               }
+                               modifyText(null);
+                       }
+                       
+                       public void focusGained(FocusEvent e) {
+                               if (fEmptyText.equals(fText.getText())) {
+                                       fText.setForeground(getForeground());
+                                       fText.setText(""); //$NON-NLS-1$
+                               }
+                       }
+                       
+                       public void modifyText(ModifyEvent e) {
+                               fRefreshJob.cancel();
+                               fRefreshJob.schedule(500);
+                       }
+               
+                       private void selectMatches() {
+                               if (fMatchers != null) {
+                                       Tree tree = fViewer.getTree();
+                                       List selection = new ArrayList();
+                                       findElements(tree.getItems(), selection);
+                                       fViewer.setSelection(new StructuredSelection(selection), true);
+                               } else {
+                                       fViewer.setSelection(StructuredSelection.EMPTY);
+                               }
+                       }
+
+                       private Object findElements(TreeItem items[], List selection) {
+                               ILabelProvider labelProvider = (ILabelProvider) fViewer.getLabelProvider();
+                               for (int i = 0; i < items.length; i++) {
+                                       Object element = items[i].getData();
+                                       if (!(element instanceof IContainer) && (!(element instanceof File) || !((File) element).isDirectory())) {
+                                               for (int j = 0; j < fMatchers.length; j++) {
+                                                       if (fMatchers[j].match(labelProvider.getText(element)))
+                                                               selection.add(element);
+                                               }
+                                       }
+                                       findElements(items[i].getItems(), selection);
+                               }
+
+                               return null;
+                       }
+
+                       protected void setViewer(TreeViewer viewer) {
+                               fViewer = viewer;
+                               fViewer.setUseHashlookup(true);
+                       }
+               }
+
+               private TreeViewer fWorkspaceViewer;
+               private TreeViewer fFileSystemViewer;
+               private Label fStatusLabel;
+               private List fWorkspaceSelection;
+               private List fFileSystemSelection;
+               private String fText;
+               private boolean fMultiSelection;
+               private boolean fShowFiles;
+               private String fInitialSelection;
+
+               private FileDialog(String text) {
+                       super(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
+                       setShellStyle(getShellStyle() | SWT.SHELL_TRIM);
+                       fText = text;
+               }
+               
+               protected void configureShell(Shell newShell) {
+                       super.configureShell(newShell);
+                       newShell.setText(fText);
+               }
+
+               protected Control createDialogArea(Composite parent) {
+                       Composite control = (Composite) super.createDialogArea(parent);
+                       fWorkspaceViewer = createWorkspaceArea(control);
+                       fFileSystemViewer = createFileSystemArea(control);
+                       fWorkspaceViewer.addSelectionChangedListener(this);
+                       fFileSystemViewer.addSelectionChangedListener(this);
+                       ISelectionChangedListener listener = new ISelectionChangedListener() {
+                               public void selectionChanged(SelectionChangedEvent event) {
+                                       if (fMultiSelection)
+                                               return;
+                                       fWorkspaceViewer.removeSelectionChangedListener(this);
+                                       fFileSystemViewer.removeSelectionChangedListener(this);
+                                       (event.getSource() == fFileSystemViewer ? fWorkspaceViewer : fFileSystemViewer).
+                                                       setSelection(StructuredSelection.EMPTY);
+                                       fWorkspaceViewer.addSelectionChangedListener(this);
+                                       fFileSystemViewer.addSelectionChangedListener(this);
+                               }
+                       };
+                       fWorkspaceViewer.addSelectionChangedListener(listener);
+                       fFileSystemViewer.addSelectionChangedListener(listener);
+                       
+                       GridData data = (GridData) control.getLayoutData();
+                       data.widthHint = convertWidthInCharsToPixels(80);
+                       
+                       fStatusLabel = new Label(control, SWT.LEFT | SWT.WRAP);
+                       fStatusLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+                       
+                       applyDialogFont(control);
+                       setInitialSelection();
+                       return control;
+               }
+
+               private void setInitialSelection() {
+                       if (fInitialSelection == null)
+                               return;
+                       fFileSystemViewer.setSelection(new StructuredSelection(new File(fInitialSelection)), true);
+                       try {
+                               fWorkspaceViewer.setSelection(new StructuredSelection(ResourcesPlugin.getWorkspace().
+                                               getRoot().getFile(new Path(fInitialSelection))), true);
+                       } catch (Exception ignore) {
+                       }
+               }
+
+               private TreeViewer createWorkspaceArea(Composite parent) {
+                       Composite composite = new Composite(parent, SWT.NONE);
+                       composite.setLayout(new GridLayout(1, true));
+                       composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+                       FilterArea filterArea = null;
+                       if (fUseFilter)
+                               filterArea = new FilterArea(composite, ActionMessages.getString("DialogAction.0")); //$NON-NLS-1$
+                       TreeViewer viewer = new TreeViewer(composite, SWT.BORDER | (fMultiSelection ? SWT.MULTI : SWT.SINGLE));
+                       if (filterArea != null)
+                               filterArea.setViewer(viewer);
+                       viewer.setContentProvider(new WorkbenchContentProvider());
+                       viewer.setLabelProvider(new WorkbenchLabelProvider());
+                       viewer.setSorter(new ResourceSorter(ResourceSorter.NAME));
+                       if (!fShowFiles)
+                               viewer.addFilter(new FileFilter());
+                       viewer.setInput(ResourcesPlugin.getWorkspace().getRoot());
+                       GridData data = new GridData(GridData.FILL_BOTH);
+                       data.heightHint = convertHeightInCharsToPixels(10);
+                       viewer.getControl().setLayoutData(data);
+                       return viewer;
+               }
+
+               private TreeViewer createFileSystemArea(Composite parent) {
+                       Composite composite = new Composite(parent, SWT.NONE);
+                       composite.setLayout(new GridLayout(1, true));
+                       composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+                       FilterArea filterArea = null;
+                       if (fUseFilter)
+                               filterArea = new FilterArea(composite, ActionMessages.getString("DialogAction.1")); //$NON-NLS-1$
+                       TreeViewer viewer = new TreeViewer(composite, SWT.BORDER | (fMultiSelection ? SWT.MULTI : SWT.SINGLE));
+                       if (filterArea != null)
+                               filterArea.setViewer(viewer);
+                       viewer.setContentProvider(new FileSystemContentProvider());
+                       viewer.setLabelProvider(new FileSystemLabelProvider());
+                       viewer.setSorter(new FileSorter());
+                       if (!fShowFiles)
+                               viewer.addFilter(new FileFilter());
+                       viewer.setInput(File.listRoots());
+                       GridData data = new GridData(GridData.FILL_BOTH);
+                       data.heightHint = convertHeightInCharsToPixels(10);
+                       viewer.getControl().setLayoutData(data);
+                       return viewer;
+               }
+               
+               protected void okPressed() {
+                       fWorkspaceSelection = toList(((IStructuredSelection) fWorkspaceViewer.getSelection()));
+                       fFileSystemSelection = toList(((IStructuredSelection) fFileSystemViewer.getSelection()));
+                       super.okPressed();
+               }
+
+               public String[] getFileNames() {
+                       List allNames = new ArrayList();
+                       if (fWorkspaceSelection != null)
+                               allNames.addAll(fWorkspaceSelection);
+                       if (fFileSystemSelection != null)
+                               allNames.addAll(fFileSystemSelection);
+                       return (String[]) allNames.toArray(new String[allNames.size()]);
+               }
+               
+               private List toList(IStructuredSelection selection) {
+                       List list = selection.toList();
+                       for (int i = 0; i < list.size(); i++) {
+                               Object element = list.get(i);
+                               if (element instanceof IResource)
+                                       list.set(i, ((IResource) element).getLocation().toFile().getAbsolutePath());
+                               else if (element instanceof File)
+                                       list.set(i, ((File) element).getAbsolutePath());
+                       }
+                       return list;
+               }
+
+               public void setMultiSelection(boolean multiSelection) {
+                       fMultiSelection = multiSelection;
+               }
+
+               public void setShowFiles(boolean showFiles) {
+                       fShowFiles = showFiles;
+               }
+
+               public void setSelection(String path) {
+                       fInitialSelection = path;
+               }
+               
+               public void selectionChanged(SelectionChangedEvent event) {
+                       updateStatusText();
+               }
+
+               private void updateStatusText() {
+                       int wsSize = ((IStructuredSelection) fWorkspaceViewer.getSelection()).size();
+                       int fsSize = ((IStructuredSelection) fFileSystemViewer.getSelection()).size();
+                       fStatusLabel.setText(ActionMessages.getFormattedString("DialogAction.2", //$NON-NLS-1$
+                                       new Object[] { new Integer(wsSize), new Integer(fsSize) }));
+               }
+       }
+
+       private boolean fUseFilter;
+
+       protected DialogAction(String text, StructuredViewer viewer, boolean useFilter) {
+               super(text, viewer);
+               fUseFilter = useFilter;
+       }
+
+       protected String[] openDialog(String text, String path, boolean multiSelection, boolean showFiles) {
+               FileDialog dialog = new FileDialog(text);
+               dialog.setMultiSelection(multiSelection);
+               dialog.setShowFiles(showFiles);
+               dialog.setSelection(path);
+               dialog.open();
+               return dialog.getFileNames();
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/EditorAction.java b/org.tizen.common.externals/src/zipeditor/actions/EditorAction.java
new file mode 100644 (file)
index 0000000..4e41e11
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import org.eclipse.jface.action.Action;
+
+import zipeditor.ZipEditor;
+
+public abstract class EditorAction extends Action {
+       protected ZipEditor fEditor;
+
+       protected EditorAction(String text, ZipEditor editor) {
+               super(text);
+               fEditor = editor;
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/ExtractAction.java b/org.tizen.common.externals/src/zipeditor/actions/ExtractAction.java
new file mode 100644 (file)
index 0000000..82f5b85
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import java.io.File;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.StructuredViewer;
+
+import zipeditor.ZipEditorPlugin;
+import zipeditor.model.Node;
+import zipeditor.operations.ExtractOperation;
+
+public class ExtractAction extends DialogAction {
+       private class RefreshJob extends Job {
+               public RefreshJob() {
+                       super(ActionMessages.getString("ExtractAction.3")); //$NON-NLS-1$
+               }
+
+               protected IStatus run(IProgressMonitor monitor) {
+                       finished();
+                       return Status.OK_STATUS;
+               }
+
+       };
+
+       private String fSelectedFolder;
+       public ExtractAction(StructuredViewer viewer) {
+               super(ActionMessages.getString("ExtractAction.0"), viewer, false); //$NON-NLS-1$
+               setToolTipText(ActionMessages.getString("ExtractAction.1")); //$NON-NLS-1$
+               setImageDescriptor(ZipEditorPlugin.getImageDescriptor("icons/extract.gif")); //$NON-NLS-1$
+       }
+
+       public void run() {
+               Node[] nodes = getSelectedNodes();
+               if (nodes.length == 0)
+                       nodes = new Node[] { getViewerInputAsNode() };
+               String[] folder = openDialog(ActionMessages.getString("ExtractAction.2"), fSelectedFolder, false, false); //$NON-NLS-1$
+               if (folder != null && folder.length > 0) {
+                       ExtractOperation operation = new ExtractOperation();
+                       operation.setRefreshJob(new RefreshJob());
+                       fSelectedFolder = operation.execute(nodes, new File(folder[0]), true, false).getAbsolutePath();
+               }
+       }
+
+       protected void finished() {
+               if (fSelectedFolder == null)
+                       return;
+               try {
+                       IContainer[] resources = ResourcesPlugin.getWorkspace().getRoot().findContainersForLocation(
+                                       new Path(fSelectedFolder));
+                       if (resources != null && resources.length > 0)
+                               resources[0].refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
+               } catch (CoreException e) {
+                       ZipEditorPlugin.log(e);
+               }
+       }
+
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/FileOpener.java b/org.tizen.common.externals/src/zipeditor/actions/FileOpener.java
new file mode 100644 (file)
index 0000000..6bad165
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.editors.text.EditorsUI;
+
+import zipeditor.PreferenceConstants;
+import zipeditor.PreferenceInitializer;
+import zipeditor.Utils;
+import zipeditor.ZipEditorPlugin;
+import zipeditor.model.Node;
+
+public class FileOpener {
+       private final static int MAX_RECENTLY_USED_FILTERS = 5;
+
+       public static class Editor {
+               private String path;
+               private String label;
+               private IEditorDescriptor descriptor;
+               protected Editor(IEditorDescriptor descriptor) {
+                       this.descriptor = descriptor;
+                       label = descriptor.getLabel();
+               }
+
+               public Editor(String string) {
+                       int _1st = string.indexOf(255);
+                       if (_1st != -1) {
+                               label = string.substring(0, _1st);
+                               path = string.substring(_1st + 1);
+                       } else {
+                               _1st = string.indexOf(254);
+                               if (_1st != -1)
+                                       label = string.substring(0, _1st);
+                               descriptor = PlatformUI.getWorkbench().getEditorRegistry().findEditor(string.substring(_1st + 1));
+                       }
+               }
+               
+               protected Editor(String label, String path) {
+                       this.label = label;
+                       this.path = path;
+               }
+               
+               public String getLabel() {
+                       return label;
+               }
+               
+               public String getPath() {
+                       return path;
+               }
+               
+               public IEditorDescriptor getDescriptor() {
+                       return descriptor;
+               }
+               
+               public void setLabel(String label) {
+                       this.label = label;
+               }
+               
+               public void setPath(String path) {
+                       this.path = path;
+               }
+               
+               public boolean equals(Object obj) {
+                       return obj != null && obj.toString().equals(toString());
+               }
+
+               public String toString() {
+                       return label + (descriptor != null ? (char) 254 + descriptor.getId()
+                                       : (char) 255 + path);
+               }
+       };
+
+       private final IWorkbenchPage fPage;
+       private final Node fNode;
+       
+       public FileOpener(IWorkbenchPage page, Node node) {
+               fPage = page;
+               fNode = node;
+       }
+
+       public void openFromOther(IFileStore file, Editor editor) {
+               if (editor.getDescriptor() == null) {
+                       try {
+                               processCommand(file, editor);
+                               addToRecentlyUsedExecutables(editor);
+                               ZipEditorPlugin.getDefault().addFileMonitor(new File(file.toURI()), fNode);
+                       } catch (Exception e) {
+                               ZipEditorPlugin.log(e);
+                               ErrorDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+                                               ActionMessages.getString("FileOpener.0"), ActionMessages.getString("FileOpener.1"), //$NON-NLS-1$ //$NON-NLS-2$
+                                               ZipEditorPlugin.createErrorStatus(e.getClass().getName(), e));
+                       }
+               } else {
+                       if (!file.fetchInfo().isDirectory() && file.fetchInfo().exists()) {
+                               IEditorInput input = Utils.createEditorInput(file);
+                               String editorId = editor.getDescriptor().getId();
+                               try {
+                                       fPage.openEditor(input, editorId);
+                                       ZipEditorPlugin.getDefault().addFileMonitor(new File(file.toURI()), fNode);
+                                       addToRecentlyUsedExecutables(editor);
+                               } catch (PartInitException e) {
+                                       ZipEditorPlugin.log(e);
+                               }
+                       }
+               }
+       }
+
+       private void processCommand(IFileStore file, Editor editor) throws Exception {
+               String commandString = editor.getPath();
+               commandString = replaceAll(commandString, "$p", file.toString()); //$NON-NLS-1$
+               commandString = replaceAll(commandString, "$f", file.getName()); //$NON-NLS-1$
+               commandString = replaceAll(commandString, "$z", fNode.getModel().getZipPath().getAbsolutePath()); //$NON-NLS-1$
+               int dotIndex = file.getName().lastIndexOf('.');
+               commandString = replaceAll(commandString, "$n", file.getName().substring(0, dotIndex != -1 ? dotIndex : file.getName().length())); //$NON-NLS-1$
+               if (commandString.equals(editor.getPath()))
+                       commandString += ' ' + file.toString();
+               String outCommand = null;
+               int pipeIndex = commandString.indexOf('|');
+               if (pipeIndex != -1) {
+                       outCommand = commandString.substring(pipeIndex + 1);
+                       commandString = commandString.substring(0, pipeIndex);
+               }
+        int extIndex = commandString.indexOf("$x"); //$NON-NLS-1$
+        String ext = null;
+               if (extIndex != -1) {
+                       int endIndex = (ext = commandString.substring(extIndex + 2).trim()).indexOf(' ');
+                       ext = ext.substring(0, endIndex == -1 ? ext.length() : endIndex);
+                       commandString = commandString.substring(0, extIndex) + commandString.substring(commandString.indexOf(ext) + ext.length());
+               }
+               Process process = Runtime.getRuntime().exec(commandString);
+               if (outCommand == null)
+                       return;
+               final InputStream stdIn = process.getInputStream();
+               final InputStream stdErr = process.getErrorStream();
+               int defaultEditorIndex = outCommand.indexOf("$i"); //$NON-NLS-1$
+               int editorIdIndex = outCommand.indexOf("$e"); //$NON-NLS-1$
+               if (defaultEditorIndex != -1 || editorIdIndex != -1) {
+                       String editorId = EditorsUI.DEFAULT_TEXT_EDITOR_ID;
+                       if (editorIdIndex != -1) {
+                               editorId = outCommand.substring(editorIdIndex + 2).trim();
+                               if (editorId.indexOf(' ') != -1)
+                                       editorId = editorId.substring(0, editorId.indexOf(' ')).trim();
+                       }
+                       final File tmpFile = File.createTempFile("internal", ext, fNode.getModel().getTempDir()); //$NON-NLS-1$
+                       final FileOutputStream out = new FileOutputStream(tmpFile);
+                       Thread.sleep(100);
+                       new Thread(new Runnable() {
+                               public void run() {
+                                       try {
+                                               Utils.readAndWrite(stdErr, out, false);
+                                       } catch (IOException e) {
+                                               e.printStackTrace();
+                                       }
+                               }
+                       }, "ErrReader").start(); //$NON-NLS-1$
+                       Thread.sleep(100);
+                       new Thread(new Runnable() {
+                               public void run() {
+                                       try {
+                                               Utils.readAndWrite(stdIn, out, false);
+                                       } catch (IOException e) {
+                                               e.printStackTrace();
+                                       }
+                               }
+                       }, "InReader").start(); //$NON-NLS-1$
+                       process.waitFor();
+                       Thread.sleep(100);
+                       out.flush();
+                       if (out.getChannel().isOpen())
+                               out.close();
+                       fPage.openEditor(Utils.createEditorInput(Utils.getFileStore(tmpFile)), editorId);
+               } else {
+                       Process outCommandProcess = Runtime.getRuntime().exec(outCommand);
+                       BufferedOutputStream out = new BufferedOutputStream(outCommandProcess.getOutputStream());
+                       Utils.readAndWrite(stdIn, out, true);
+               }
+       }
+       
+       private String replaceAll(String string, String what, String replacement) {
+               int index = string.indexOf(what);
+               if (index == -1)
+                       return string;
+               return string.substring(0, index) + replacement + replaceAll(string.substring(index + what.length()), what, replacement);
+       }
+
+       private void addToRecentlyUsedExecutables(Editor editor) {
+               IPreferenceStore store = ZipEditorPlugin.getDefault().getPreferenceStore();
+               Editor[] recentlyUsedEditors = (Editor[]) PreferenceInitializer.split(store.getString(PreferenceConstants.RECENTLY_USED_EDITORS), PreferenceConstants.RECENTLY_USED_SEPARATOR, Editor.class);
+               List newEditors = new ArrayList(Arrays.asList(recentlyUsedEditors));
+               for (int i = 0; i < recentlyUsedEditors.length; i++) {
+                       if (!editor.getLabel().equals(recentlyUsedEditors[i].getLabel()))
+                               continue;
+                       newEditors.remove(i);
+               }
+               newEditors.add(0, editor.toString());
+               if (newEditors.size() > MAX_RECENTLY_USED_FILTERS)
+                       newEditors = newEditors.subList(0, MAX_RECENTLY_USED_FILTERS);
+               store.setValue(PreferenceConstants.RECENTLY_USED_EDITORS, PreferenceInitializer.join(newEditors.toArray(), PreferenceConstants.RECENTLY_USED_SEPARATOR));
+       }
+
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/MostRecentlyUsedMenu.java b/org.tizen.common.externals/src/zipeditor/actions/MostRecentlyUsedMenu.java
new file mode 100644 (file)
index 0000000..d608b79
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.ContributionItem;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.ui.PlatformUI;
+
+import zipeditor.PreferenceConstants;
+import zipeditor.PreferenceInitializer;
+import zipeditor.ZipEditorPlugin;
+import zipeditor.actions.FileOpener.Editor;
+import zipeditor.model.FileAdapter;
+
+public class MostRecentlyUsedMenu extends ContributionItem {
+       private class ExtractJob extends Job {
+               private Editor fEditor;
+
+               public ExtractJob(Editor editor) {
+                       super(ActionMessages.getString("MostRecentlyUsedMenu.0")); //$NON-NLS-1$
+                       fEditor = editor;
+               }
+
+               protected IStatus run(IProgressMonitor monitor) {
+                       monitor.beginTask(ActionMessages.getString("MostRecentlyUsedMenu.1"), 1); //$NON-NLS-1$
+                       try {
+                               final Object adapter = fFileAdapter.getAdapter(IFileStore.class);
+                               PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
+                                       public void run() {
+                                               fFileOpener.openFromOther((IFileStore) adapter, fEditor);
+                                       }
+                               });
+                       } finally {
+                               monitor.done();
+                       }
+                       return Status.OK_STATUS;
+               }
+       }
+       private FileOpener fFileOpener;
+       private FileAdapter fFileAdapter;
+
+       public MostRecentlyUsedMenu(FileOpener fileOpener, FileAdapter fileAdapter) {
+               fFileOpener = fileOpener;
+               fFileAdapter = fileAdapter;
+       }
+
+       public boolean isDynamic() {
+               return true;
+       }
+
+       public void fill(Menu menu, int index) {
+               createMostRecentlyUsedItems(menu, index);
+       }
+
+       private void createMostRecentlyUsedItems(Menu menu, int index) {
+               IPreferenceStore store = ZipEditorPlugin.getDefault().getPreferenceStore();
+               Editor[] recentlyUsedEditors = (Editor[]) PreferenceInitializer.split(store.getString(PreferenceConstants.RECENTLY_USED_EDITORS), PreferenceConstants.RECENTLY_USED_SEPARATOR, Editor.class);
+               for (int i = 0, j = 0; i < recentlyUsedEditors.length; i++) {
+                       final Editor editor = recentlyUsedEditors[i];
+                       if (editor == null || editor.getLabel() == null) // error case
+                               continue;
+                       MenuItem item = new MenuItem(menu, SWT.PUSH, index + j++);
+                       item.setText(editor.getLabel());
+                       if (editor.getDescriptor() != null)
+                               item.setImage(ZipEditorPlugin.getImage(editor.getDescriptor().getImageDescriptor()));
+                       Listener listener = new Listener() {
+                               public void handleEvent(Event event) {
+                                       switch (event.type) {
+                                       case SWT.Selection:
+                                               new ExtractJob(editor).schedule();
+                                               break;
+                                       }
+                               }
+                       };
+                       item.addListener(SWT.Selection, listener);
+               }
+       }
+
+
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/MultiPropertyDialogAction.java b/org.tizen.common.externals/src/zipeditor/actions/MultiPropertyDialogAction.java
new file mode 100644 (file)
index 0000000..ce21ece
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.preference.PreferenceManager;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.IShellProvider;
+import org.eclipse.jface.window.Window;
+import org.eclipse.ui.dialogs.PropertyDialogAction;
+
+import zipeditor.MultiPreferenceDialog;
+
+public class MultiPropertyDialogAction extends PropertyDialogAction {
+       private IShellProvider fShellProvider;
+
+       public MultiPropertyDialogAction(IShellProvider shell, ISelectionProvider provider) {
+               super(shell, provider);
+               fShellProvider = shell;
+       }
+
+       public void selectionChanged(IStructuredSelection selection) {
+               setEnabled(!selection.isEmpty());
+       }
+
+       public void run() {
+               List elements = getStructuredSelection().toList();
+               Window dialog = new MultiPreferenceDialog(fShellProvider.getShell(),
+                               new PreferenceManager(), (IAdaptable[]) elements
+                                               .toArray(new IAdaptable[elements.size()]));
+               dialog.open();
+       }
+}
\ No newline at end of file
diff --git a/org.tizen.common.externals/src/zipeditor/actions/NewFolderAction.java b/org.tizen.common.externals/src/zipeditor/actions/NewFolderAction.java
new file mode 100644 (file)
index 0000000..aa5b24b
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.window.Window;
+
+import zipeditor.model.Node;
+
+public class NewFolderAction extends ViewerAction {
+       public NewFolderAction(StructuredViewer viewer) {
+               super(ActionMessages.getString("NewFolderAction.0"), viewer); //$NON-NLS-1$
+       }
+
+       public void run() {
+               Node parent = null;
+               Node[] nodes = getSelectedNodes();
+               if (nodes.length == 1)
+                       parent = nodes[0].isFolder() ? nodes[0] : nodes[0].getParent();
+               else
+                       parent = getViewerInputAsNode();
+               
+               InputDialog dialog = new InputDialog(getViewer().getControl().getShell(),
+                               ActionMessages.getString("NewFolderAction.1"), ActionMessages.getString("NewFolderAction.2"), null, null); //$NON-NLS-1$ //$NON-NLS-2$
+               if (dialog.open() != Window.OK)
+                       return;
+               String newName = dialog.getValue();
+               Node newNode = parent.getModel().createFolderNode(parent, newName);
+               getViewer().setSelection(new StructuredSelection(newNode), true);
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/OpenAction.java b/org.tizen.common.externals/src/zipeditor/actions/OpenAction.java
new file mode 100644 (file)
index 0000000..ec5fe7f
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+import zipeditor.Utils;
+import zipeditor.model.Node;
+
+public class OpenAction extends ViewerAction {
+       
+       public OpenAction(StructuredViewer viewer) {
+               super(ActionMessages.getString("OpenAction.0"), viewer); //$NON-NLS-1$
+               setToolTipText(ActionMessages.getString("OpenAction.1")); //$NON-NLS-1$
+               setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().
+                               getImageDescriptor(ISharedImages.IMG_OBJ_FILE));
+       }
+
+       public void run() {
+               Node[] nodes = getSelectedNodes();
+               if (nodes.length == 1 && nodes[0].isFolder() && getViewer() instanceof TreeViewer) {
+                       TreeViewer viewer = (TreeViewer) getViewer();
+                       viewer.setExpandedState(nodes[0], !viewer.getExpandedState(nodes[0]));
+               } else {
+                       Utils.openFilesFromNodes(nodes);
+               }
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/OpenActionGroup.java b/org.tizen.common.externals/src/zipeditor/actions/OpenActionGroup.java
new file mode 100644 (file)
index 0000000..9eba6f9
--- /dev/null
@@ -0,0 +1,125 @@
+package zipeditor.actions;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.action.GroupMarker;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionGroup;
+import org.eclipse.ui.navigator.ICommonActionConstants;
+
+import zipeditor.Utils;
+import zipeditor.actions.DeferredMenuManager.MenuJob;
+import zipeditor.model.FileAdapter;
+import zipeditor.model.Node;
+
+public class OpenActionGroup extends ActionGroup {
+       private OpenAction fOpenAction;
+       private boolean fDisposed;
+
+       private final static String GROUP_OPEN_RECENTLY_USED = "openRecentlyUsed"; //$NON-NLS-1$
+
+       public OpenActionGroup(StructuredViewer viewer, boolean useOpenActionHandler) {
+               fOpenAction = new OpenAction(viewer);
+               if (useOpenActionHandler)
+                       fOpenAction.setActionDefinitionId(ICommonActionConstants.OPEN);
+       }
+       
+       public void dispose() {
+               fDisposed = true;
+               super.dispose();
+       }
+
+       public void fillContextMenu(IMenuManager menu) {
+               IStructuredSelection selection = (IStructuredSelection) getContext().getSelection();
+               boolean onlyFilesSelected = !selection.isEmpty() && Utils.allNodesAreFileNodes(selection);
+               if (onlyFilesSelected) {
+                       if (menu.find(IWorkbenchActionConstants.MB_ADDITIONS) != null) {
+                               menu.appendToGroup(IWorkbenchActionConstants.MB_ADDITIONS, fOpenAction);
+                               menu.appendToGroup(IWorkbenchActionConstants.MB_ADDITIONS, new GroupMarker(GROUP_OPEN_RECENTLY_USED));
+                       } else {
+                               menu.add(fOpenAction);
+                               menu.add(new GroupMarker(GROUP_OPEN_RECENTLY_USED));
+                       }
+               if (selection.size() == 1) {
+                       Object element = selection.getFirstElement();
+                       if (element instanceof Node) {
+                               Node node = (Node) element;
+                           FileAdapter adapter = new FileAdapter(node);
+                               FileOpener fileOpener = new FileOpener(getActivePage(), node);
+                               fillOpenWithMenu(menu, adapter, fileOpener);
+                               fillMostRecentlyUsedItems(menu, adapter, fileOpener);
+                       }
+               }
+               }
+       }
+
+       public void fillToolBarManager(IToolBarManager manager) {
+               manager.add(new Separator());
+               manager.add(fOpenAction);
+       }
+       
+       public void fillActionBars(IActionBars actionBars) {
+               if (actionBars.getGlobalActionHandler(fOpenAction.getActionDefinitionId()) == null)
+                       actionBars.setGlobalActionHandler(fOpenAction.getActionDefinitionId(), fOpenAction);
+               updateActionBars();
+       }
+       
+       private void fillOpenWithMenu(IMenuManager menu, final FileAdapter fileAdapter, final FileOpener fileOpener) {
+        boolean isRunning = DeferredMenuManager.isRunning(fileAdapter, null);
+               if (fileAdapter.isAdapted() && !isRunning) {
+               MenuManager subMenu = new MenuManager(ActionMessages.getString("OpenActionGroup.0"), PlatformUI.PLUGIN_ID + ".OpenWithSubMenu");  //$NON-NLS-1$//$NON-NLS-2$
+                       doAddToMenu(subMenu, null, fileAdapter);
+                       if (menu.find(IWorkbenchActionConstants.MB_ADDITIONS) != null)
+                               menu.appendToGroup(IWorkbenchActionConstants.MB_ADDITIONS, subMenu);
+                       else
+                               menu.add(subMenu);
+               } else {
+                       MenuJob menuJob = new MenuJob(fileAdapter, null) {
+                               protected IStatus addToMenu(IProgressMonitor monitor, IMenuManager menu) {
+                                       if (!fDisposed)
+                                               doAddToMenu(menu, fileOpener, fileAdapter);
+                                       return Status.OK_STATUS;
+                               }
+                       };
+                       DeferredMenuManager.addToMenu(menu, IWorkbenchActionConstants.MB_ADDITIONS, ActionMessages.getString("OpenActionGroup.0"), PlatformUI.PLUGIN_ID + ".OpenWithSubMenu", menuJob); //$NON-NLS-1$ //$NON-NLS-2$
+               }
+       }
+
+       private void doAddToMenu(IMenuManager subMenu, FileOpener fileOpener, FileAdapter adapter) {
+        subMenu.add(new OpenWithMenu(getActivePage(), fileOpener, adapter));
+       }
+       
+       private void fillMostRecentlyUsedItems(IMenuManager menu, FileAdapter fileAdapter, FileOpener fileOpener) {
+               if (menu.find(IWorkbenchActionConstants.MB_ADDITIONS) != null)
+                       menu.appendToGroup(IWorkbenchActionConstants.MB_ADDITIONS, new MostRecentlyUsedMenu(fileOpener, fileAdapter));
+               else
+                       menu.add(new MostRecentlyUsedMenu(fileOpener, fileAdapter));
+       }
+
+       private IWorkbenchPage getActivePage() {
+               if (Utils.isUIThread())
+                       return PlatformUI.getWorkbench().getActiveWorkbenchWindow()
+                                       .getActivePage();
+               else {
+                       final IWorkbenchPage[] result = { null };
+                       Display.getDefault().syncExec(new Runnable() {
+                               public void run() {
+                                       result[0] = PlatformUI.getWorkbench()
+                                                       .getActiveWorkbenchWindow().getActivePage();
+                               }
+                       });
+                       return result[0];
+               }
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/OpenWithMenu.java b/org.tizen.common.externals/src/zipeditor/actions/OpenWithMenu.java
new file mode 100644 (file)
index 0000000..83ffb2d
--- /dev/null
@@ -0,0 +1,727 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import java.io.File;
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.TreeSet;
+
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ContributionItem;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.fieldassist.IContentProposal;
+import org.eclipse.jface.fieldassist.IContentProposalProvider;
+import org.eclipse.jface.fieldassist.TextContentAdapter;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorRegistry;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.SelectionDialog;
+import org.eclipse.ui.dialogs.SelectionStatusDialog;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+
+import zipeditor.PreferenceConstants;
+import zipeditor.PreferenceInitializer;
+import zipeditor.Utils;
+import zipeditor.ZipEditorPlugin;
+import zipeditor.actions.FileOpener.Editor;
+import zipeditor.model.Node;
+
+public class OpenWithMenu extends ContributionItem {
+       private class ExecutableSelectionDialog extends SelectionStatusDialog {
+               private class EditDialog extends SelectionDialog {
+                       // be compatible with release before 3.6
+                       private class ContentProposal implements IContentProposal {
+                               private String content;
+                               private String label;
+                               private String description;
+                               private int cursorPosition;
+                               public ContentProposal(String content, String label, String description) {
+                                       this.content = content;
+                                       this.label = label;
+                                       this.description = description;
+                                       cursorPosition = content.length();
+                               }
+                               public String getContent() {
+                                       return content;
+                               }
+                               public int getCursorPosition() {
+                                       return cursorPosition;
+                               }
+                               public String getLabel() {
+                                       return label;
+                               }
+                               public String getDescription() {
+                                       return description;
+                               }
+                       }
+
+                       private Editor fEditor;
+                       private Text fLabel;
+                       private Text fPath;
+                       private Button fBrowse;
+
+                       private EditDialog(Editor editor) {
+                               super(ExecutableSelectionDialog.this.getShell());
+                               setShellStyle(getShellStyle() | SWT.RESIZE);
+                               fEditor = editor;
+                               setTitle(ActionMessages.getString("OpenWithMenu.16")); //$NON-NLS-1$
+                       }
+
+                       protected Control createDialogArea(Composite parent) {
+                               Composite control = (Composite) super.createDialogArea(parent);
+                               ((GridLayout) control.getLayout()).numColumns = 2;
+                               Label label = new Label(control, SWT.LEFT);
+                               label.setText(ActionMessages.getString("OpenWithMenu.14")); //$NON-NLS-1$
+                               fLabel = createText(control, fEditor.getLabel());
+                               label = new Label(control, SWT.LEFT);
+                               label.setText(ActionMessages.getString("OpenWithMenu.15")); //$NON-NLS-1$
+                               fPath = createText(control, fEditor.getPath());
+                               new ContentAssistCommandAdapter(fPath, new TextContentAdapter(),
+                                               new IContentProposalProvider() {
+                                                       public IContentProposal[] getProposals(String contents,
+                                                                       int position) {
+                                                               return doGetProposals(contents, position);
+                                                       }
+                                               }, ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS,
+                                               new char[0], true);
+                               fBrowse = new Button(control, SWT.PUSH);
+                               fBrowse.setText(ActionMessages.getString("OpenWithMenu.19")); //$NON-NLS-1$
+                               fBrowse.addSelectionListener(new SelectionAdapter() {
+                                       public void widgetSelected(SelectionEvent e) {
+                                               handleBrowseSelected();
+                                       }
+                               });
+                               applyDialogFont(control);
+                               return control;
+                       }
+                       
+                       private Text createText(Composite parent, String string) {
+                               Text text = new Text(parent, SWT.BORDER);
+                               if (string != null)
+                                       text.setText(string);
+                               GridData data = new GridData(GridData.FILL_HORIZONTAL);
+                               data.widthHint = convertWidthInCharsToPixels(20);
+                               text.setLayoutData(data);
+                               return text;
+                       }
+                       
+                       protected void okPressed() {
+                               fEditor.setLabel(fLabel.getText());
+                               fEditor.setPath(fPath.getText());
+                               super.okPressed();
+                       }
+                       
+                       public Editor getEditor() {
+                               return fEditor;
+                       }
+                       
+                       private void handleBrowseSelected() {
+                               FileDialog dialog = new FileDialog(getShell(), SWT.OPEN);
+                               if (fLastFilterPath != null)
+                                       dialog.setFilterPath(fLastFilterPath);
+                               String selectedFile = dialog.open();
+                               if (selectedFile == null)
+                                       return;
+                               int lastPoint = selectedFile.lastIndexOf('.');
+                               int lastSlash = selectedFile.lastIndexOf('/');
+                               if (lastSlash == -1)
+                                       lastSlash = selectedFile.lastIndexOf('\\');
+                               String label = selectedFile.substring(lastSlash + 1, lastPoint != -1 ? lastPoint : selectedFile.length());
+                               if (fLabel.getText().length() == 0)
+                                       fLabel.setText(label);
+                               fPath.setText(selectedFile);
+                       }
+
+                       private IContentProposal[] doGetProposals(String contents, int position) {
+                               String all = ActionMessages.getString("OpenWithMenu.17"); //$NON-NLS-1$
+                               StringTokenizer st = new StringTokenizer(all, "\n"); //$NON-NLS-1$
+                               List proposals = new ArrayList();
+                               while (st.hasMoreElements()) {
+                                       String entry = st.nextToken();
+                                       StringTokenizer tst = new StringTokenizer(entry, " "); //$NON-NLS-1$
+                                       String value = tst.nextToken();
+                                       int wordoffset = contents.lastIndexOf(' ', position - 1) + 1;
+                                       if (wordoffset > position)
+                                               wordoffset = position;
+                                       String word = contents.substring(wordoffset, position);
+                                       if (position >= 3 && contents.substring(position - 3).startsWith("$e")) { //$NON-NLS-1$
+                                               Set set = new TreeSet(new Comparator() {
+                                                       public int compare(Object arg0, Object arg1) {
+                                                               return ((IEditorDescriptor) arg0).getLabel().compareTo(((IEditorDescriptor) arg1).getLabel());
+                                                       }
+                                               });
+                                               set.addAll(Arrays.asList(getEditorsFromRegistry()));
+                                               IEditorDescriptor[] editors = (IEditorDescriptor[]) set.toArray(new IEditorDescriptor[set.size()]);
+                                               for (int i = 0; i < editors.length; i++) {
+                                                       proposals.add(new ContentProposal(editors[i].getId(), editors[i].getLabel(), null));
+                                               }
+                                               break;
+                                       } else if (value.startsWith(word))
+                                               proposals.add(new ContentProposal(value.substring(word.length()), value, entry));
+                               }
+                               return (IContentProposal[]) proposals.toArray(new IContentProposal[proposals.size()]);
+                       }
+               };
+               
+               private class EditorDescriptorLabelProvider extends LabelProvider {
+                       public String getText(Object element) {
+                               if (!(element instanceof Editor))
+                                       return super.getText(element);
+                               Editor editor = (Editor) element;
+                               return editor.getDescriptor() != null ? editor.getDescriptor().getLabel()
+                                               : editor.getLabel();
+                       }
+                       
+                       public Image getImage(Object element) {
+                               if (!(element instanceof Editor))
+                                       return super.getImage(element);
+                               Editor editor = (Editor) element;
+                               return editor.getDescriptor() != null ? ZipEditorPlugin
+                                               .getImage(editor.getDescriptor().getImageDescriptor())
+                                               : PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE);
+                       }
+               };
+
+               private class RemoveAction extends Action {
+                       private RemoveAction() {
+                               super(ActionMessages.getString("OpenWithMenu.13")); //$NON-NLS-1$
+                       }
+                       
+                       public void run() {
+                               Object selectedEditor = ((IStructuredSelection) fTableViewer.getSelection()).getFirstElement();
+                               getExternalEditors().remove(selectedEditor);
+                               IPreferenceStore store = ZipEditorPlugin.getDefault().getPreferenceStore();
+                               ArrayList editors = new ArrayList(Arrays.asList((Editor[]) PreferenceInitializer.split(store.getString(PreferenceConstants.RECENTLY_USED_EDITORS), PreferenceConstants.RECENTLY_USED_SEPARATOR, Editor.class)));
+                               editors.remove(selectedEditor);
+                               store.setValue(PreferenceConstants.RECENTLY_USED_EDITORS, PreferenceInitializer.join(editors.toArray(), PreferenceConstants.RECENTLY_USED_SEPARATOR));
+                               fTableViewer.refresh();
+                       }
+               };
+
+               private class AddAction extends Action {
+                       private AddAction() {
+                               super(ActionMessages.getString("OpenWithMenu.18")); //$NON-NLS-1$
+                       }
+                       
+                       public void run() {
+                               addNewEditor();
+                       }
+               };
+
+               private class EditAction extends Action {
+                       private EditAction() {
+                               super(ActionMessages.getString("OpenWithMenu.12")); //$NON-NLS-1$
+                       }
+                       
+                       public void run() {
+                               EditDialog dialog = new EditDialog((Editor) ((IStructuredSelection) fTableViewer.getSelection()).getFirstElement());
+                               if (dialog.open() == Window.OK)
+                                       fTableViewer.refresh();
+                       }
+               };
+
+               private TableViewer fTableViewer;
+               private Object fSelection;
+               private String fLastFilterPath;
+               private Set fExternalEditors;
+               private Set fInternalEditors;
+               private Button fAddButton;
+               private IAction fAddAction;
+               private IAction fEditAction;
+               private IAction fRemoveAction;
+
+               public ExecutableSelectionDialog(Shell parentShell, Object initialSelection) {
+                       super(parentShell);
+                       setShellStyle(getShellStyle() | SWT.RESIZE);
+                       fSelection = initialSelection;
+                       setTitle(ActionMessages.getString("OpenWithMenu.5")); //$NON-NLS-1$
+                       fAddAction = new AddAction();
+                       fEditAction = new EditAction();
+                       fRemoveAction = new RemoveAction();
+               }
+               
+               protected Control createContents(Composite parent) {
+                       Control control = super.createContents(parent);
+                       if (fSelection != null)
+                               fTableViewer.setSelection(new StructuredSelection(fSelection));
+                       return control;
+               }
+
+               protected Control createDialogArea(Composite parent) {
+                       Composite composite = (Composite) super.createDialogArea(parent);
+                       Label label = new Label(composite, SWT.LEFT);
+                       label.setText(ActionMessages.getString("OpenWithMenu.6")); //$NON-NLS-1$
+                       label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+                       label = new Label(composite, SWT.LEFT);
+                       label.setText(ActionMessages.getString("OpenWithMenu.7") + getFileResource().getName()); //$NON-NLS-1$
+                       label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
+                       createExternalEditorGroup(composite);
+                       applyDialogFont(composite);
+                       return composite;
+               }
+               
+               private Control createExternalEditorGroup(Composite parent) {
+                       Group group = new Group(parent, SWT.NONE);
+                       group.setText(ActionMessages.getString("OpenWithMenu.8")); //$NON-NLS-1$
+                       group.setLayout(new GridLayout());
+                       group.setLayoutData(new GridData(GridData.FILL_BOTH));
+                       Button[] buttons = createRadioButtons(group);
+                       fTableViewer = createTableViewer(group);
+
+                       Composite btnComposite = new Composite(group, SWT.NONE);
+                       btnComposite.setLayout(new GridLayout(2, false));
+                       btnComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+                       fAddButton = new Button(btnComposite, SWT.PUSH);
+                       fAddButton.setText(ActionMessages.getString("OpenWithMenu.9")); //$NON-NLS-1$
+                       setButtonLayoutData(fAddButton);
+                       ((GridData) fAddButton.getLayoutData()).horizontalAlignment |= GridData.HORIZONTAL_ALIGN_BEGINNING;
+                       fAddButton.addSelectionListener(new SelectionAdapter() {
+                               public void widgetSelected(SelectionEvent e) {
+                                       handleAddButtonSelected();
+                               }
+                       });
+
+                       if (buttons[0].getText().equals(previouslySelectedRadio)) {
+                               handleExternalButtonSelected(buttons[0]);
+                               buttons[0].setSelection(true);
+                       }
+                       if (buttons[1].getText().equals(previouslySelectedRadio)) {
+                               handleInternalButtonSelected(buttons[1]);
+                               buttons[1].setSelection(true);
+                       }
+                       return group;
+               }
+
+               private Button[] createRadioButtons(Composite parent) {
+                       Button[] buttons = { null, null };
+                       Composite composite = new Composite(parent, SWT.NONE);
+                       composite.setLayout(new GridLayout(2, true));
+                       composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+                       Button button = buttons[0] = new Button(composite, SWT.RADIO);
+                       button.setText(ActionMessages.getString("OpenWithMenu.10")); //$NON-NLS-1$
+                       setButtonLayoutData(button);
+                       button.addSelectionListener(new SelectionAdapter() {
+                               public void widgetSelected(SelectionEvent e) {
+                                       handleExternalButtonSelected((Button) e.widget);
+                               }
+                       });
+                       button = buttons[1] = new Button(composite, SWT.RADIO);
+                       button.setText(ActionMessages.getString("OpenWithMenu.11")); //$NON-NLS-1$
+                       setButtonLayoutData(button);
+                       button.addSelectionListener(new SelectionAdapter() {
+                               public void widgetSelected(SelectionEvent e) {
+                                       handleInternalButtonSelected((Button) e.widget);
+                               }
+                       });
+                       return buttons;
+               }
+
+               private Set getExternalEditors() {
+                       if (fExternalEditors == null) {
+                               fExternalEditors = new HashSet();
+                               fExternalEditors.addAll(Arrays.asList(createExternalEditors(loadExecutables())));
+                       }
+                       return fExternalEditors;
+               }
+
+               private Object getInternalEditors() {
+                       if (fInternalEditors == null) {
+                               fInternalEditors = new HashSet(Arrays.asList(createInternalEditors(getEditorsFromRegistry())));
+                       }
+                       return fInternalEditors;
+               }
+
+               private IEditorDescriptor[] getEditorsFromRegistry() {
+                       try {
+                               IEditorRegistry editorRegistry = PlatformUI.getWorkbench().getEditorRegistry();
+                               return (IEditorDescriptor[]) editorRegistry.getClass().getMethod(
+                                               "getSortedEditorsFromPlugins", null).invoke(editorRegistry, null); //$NON-NLS-1$
+                       } catch (Exception e) {
+                               ZipEditorPlugin.log(e);
+                               return new IEditorDescriptor[0];
+                       }
+               }
+               
+               private TableViewer createTableViewer(Composite parent) {
+                       TableViewer viewer = new TableViewer(parent, SWT.SINGLE | SWT.BORDER);
+                       viewer.setContentProvider(new ArrayContentProvider());
+                       viewer.setLabelProvider(new EditorDescriptorLabelProvider());
+                       viewer.setSorter(new ViewerSorter());
+                       GridData data = new GridData(GridData.FILL_BOTH);
+                       data.heightHint = convertHeightInCharsToPixels(14);
+                       data.widthHint = convertWidthInCharsToPixels(45);
+                       viewer.getTable().setLayoutData(data);
+                       viewer.getTable().addSelectionListener(new SelectionAdapter() {
+                               public void widgetDefaultSelected(SelectionEvent e) {
+                                       okPressed();
+                               }
+                       });
+                       viewer.addSelectionChangedListener(new ISelectionChangedListener() {
+                               public void selectionChanged(SelectionChangedEvent event) {
+                                       updateButtons();
+                               }
+                       });
+                       MenuManager manager = new MenuManager();
+                       manager.setRemoveAllWhenShown(true);
+                       manager.addMenuListener(new IMenuListener() {
+                               public void menuAboutToShow(IMenuManager manager) {
+                                       manager.add(fAddAction);
+                                       manager.add(fEditAction);
+                                       manager.add(fRemoveAction);
+                               }
+                       });
+                       Menu contextMenu = manager.createContextMenu(viewer.getControl());
+                       viewer.getControl().setMenu(contextMenu);
+                       return viewer;
+               }
+
+               protected Control createButtonBar(Composite parent) {
+                       Control control = super.createButtonBar(parent);
+                       updateButtons();
+                       return control;
+               }
+               
+               private Editor[] createExternalEditors(String[] executablePaths) {
+                       Editor[] editors = new Editor[executablePaths.length];
+                       for (int i = 0; i < editors.length; i++) {
+                               editors[i] = new Editor(executablePaths[i]);
+                       }
+                       return editors;
+               }
+               
+               private Editor[] createInternalEditors(IEditorDescriptor[] descriptors) {
+                       Editor[] editors = new Editor[descriptors.length];
+                       for (int i = 0; i < editors.length; i++) {
+                               editors[i] = new Editor(descriptors[i]);
+                       }
+                       return editors;
+               }
+
+               private String[] loadExecutables() {
+                       IPreferenceStore store = ZipEditorPlugin.getDefault().getPreferenceStore();
+                       return (String[]) PreferenceInitializer.split(store.getString(PreferenceConstants.EXTERNAL_EDITORS), ",", String.class); //$NON-NLS-1$
+               }
+               
+               private void saveExecutables() {
+                       IPreferenceStore store = ZipEditorPlugin.getDefault().getPreferenceStore();
+                       store.setValue(PreferenceConstants.EXTERNAL_EDITORS, PreferenceInitializer.join(getExternalEditors().toArray(), ",")); //$NON-NLS-1$
+               }
+
+               private void updateButtons() {
+                       boolean empty = fTableViewer.getSelection().isEmpty();
+                       if (getButton(IDialogConstants.OK_ID) != null)
+                               getButton(IDialogConstants.OK_ID).setEnabled(!empty);
+                       fAddAction.setEnabled(fAddButton.isEnabled());
+                       fEditAction.setEnabled(fAddButton.isEnabled() && !empty);
+                       fRemoveAction.setEnabled(fAddButton.isEnabled() && !empty);
+               }
+
+               private void handleExternalButtonSelected(Button button) {
+                       fTableViewer.setInput(getExternalEditors());
+                       fAddAction.setEnabled(true);
+                       fEditAction.setEnabled(true);
+                       fRemoveAction.setEnabled(true);
+                       fAddButton.setEnabled(true);
+                       previouslySelectedRadio = button.getText();
+                       updateButtons();
+               }
+
+               private void handleInternalButtonSelected(Button button) {
+                       fTableViewer.setInput(getInternalEditors());
+                       fAddAction.setEnabled(false);
+                       fEditAction.setEnabled(false);
+                       fRemoveAction.setEnabled(false);
+                       fAddButton.setEnabled(false);
+                       previouslySelectedRadio = button.getText();
+                       updateButtons();
+               }
+
+               private void handleAddButtonSelected() {
+                       addNewEditor();
+               }
+               
+               private void addNewEditor() {
+                       EditDialog dialog = new EditDialog(new Editor(null, null));
+                       if (dialog.open() == Window.OK)
+                               addExternalEditor(dialog.getEditor());
+               }
+
+               private void addExternalEditor(Editor editor) {
+                       getExternalEditors().add(editor);
+                       fTableViewer.refresh();
+                       fTableViewer.setSelection(new StructuredSelection(editor));
+               }
+
+               public Object getSelection() {
+                       return fSelection;
+               }
+
+               protected void computeResult() {
+                       fSelection = ((IStructuredSelection) fTableViewer.getSelection()).getFirstElement();
+                       saveExecutables();
+               }
+       };
+
+       private IWorkbenchPage fPage;
+       private IAdaptable fFile;
+       private IEditorRegistry registry = PlatformUI.getWorkbench().getEditorRegistry();
+       private FileOpener fFileOpener;
+
+       private static Hashtable imageCache = new Hashtable(11);
+       private static Editor previouslySelectedEditor;
+       private static String previouslySelectedRadio;
+       public static final String ID = PlatformUI.PLUGIN_ID + ".OpenWithMenu";//$NON-NLS-1$
+       private static final int MATCH_BOTH = IWorkbenchPage.MATCH_INPUT | IWorkbenchPage.MATCH_ID;
+
+       private static final Comparator comparer = new Comparator() {
+               private Collator collator = Collator.getInstance();
+
+               public int compare(Object arg0, Object arg1) {
+                       String s1 = ((IEditorDescriptor) arg0).getLabel();
+                       String s2 = ((IEditorDescriptor) arg1).getLabel();
+                       return collator.compare(s1, s2);
+               }
+       };
+
+       public OpenWithMenu(IWorkbenchPage page, FileOpener fileOpener, IAdaptable file) {
+               super(ID);
+               fPage = page;
+               fFileOpener = fileOpener;
+               fFile = file;
+               getFileResource();
+       }
+
+       private Image getImage(IEditorDescriptor editorDesc) {
+               ImageDescriptor imageDesc = getImageDescriptor(editorDesc);
+               if (imageDesc == null) {
+                       return null;
+               }
+               Image image = (Image) imageCache.get(imageDesc);
+               if (image == null) {
+                       image = imageDesc.createImage();
+                       imageCache.put(imageDesc, image);
+               }
+               return image;
+       }
+
+       private ImageDescriptor getImageDescriptor(IEditorDescriptor editorDesc) {
+               ImageDescriptor imageDesc = null;
+               if (editorDesc == null) {
+                       imageDesc = registry.getImageDescriptor(getFileResource().getName());
+               } else {
+                       imageDesc = editorDesc.getImageDescriptor();
+               }
+               if (imageDesc == null) {
+                       if (editorDesc.getId().equals(IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID)) {
+                               imageDesc = registry.getSystemExternalEditorImageDescriptor(getFileResource().getName());
+                       }
+               }
+               return imageDesc;
+       }
+
+       private void createMenuItem(Menu menu, final IEditorDescriptor descriptor, final IEditorDescriptor preferredEditor) {
+               final MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+               boolean isPreferred = preferredEditor != null && descriptor.getId().equals(preferredEditor.getId());
+               menuItem.setSelection(isPreferred);
+               menuItem.setText(descriptor.getLabel());
+               Image image = getImage(descriptor);
+               if (image != null) {
+                       menuItem.setImage(image);
+               }
+               Listener listener = new Listener() {
+                       public void handleEvent(Event event) {
+                               switch (event.type) {
+                               case SWT.Selection:
+                                       if (menuItem.getSelection()) {
+                                               openEditor(descriptor);
+                                       }
+                                       break;
+                               }
+                       }
+               };
+               menuItem.addListener(SWT.Selection, listener);
+       }
+
+    public void fill(Menu menu, int index) {
+               IFileStore file = getFileResource();
+               if (file == null) {
+                       return;
+               }
+
+               IEditorDescriptor defaultEditor = registry.findEditor(EditorsUI.DEFAULT_TEXT_EDITOR_ID);
+
+               Object[] editors = registry.getEditors(file.getName(), Utils.getContentType(file));
+               Collections.sort(Arrays.asList(editors), comparer);
+
+               boolean defaultFound = false;
+
+               ArrayList alreadyMapped = new ArrayList();
+
+               for (int i = 0; i < editors.length; i++) {
+                       IEditorDescriptor editor = (IEditorDescriptor) editors[i];
+                       if (!alreadyMapped.contains(editor)) {
+                               createMenuItem(menu, editor, null);
+                               if (defaultEditor != null
+                                               && editor.getId().equals(defaultEditor.getId())) {
+                                       defaultFound = true;
+                               }
+                               alreadyMapped.add(editor);
+                       }
+               }
+
+               if (editors.length > 0) {
+                       new MenuItem(menu, SWT.SEPARATOR);
+               }
+
+               if (!defaultFound && defaultEditor != null) {
+                       createMenuItem(menu, defaultEditor, null);
+               }
+
+               IEditorDescriptor descriptor = registry.findEditor(IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID);
+               createMenuItem(menu, descriptor, null);
+
+               descriptor = registry.findEditor(IEditorRegistry.SYSTEM_INPLACE_EDITOR_ID);
+               if (descriptor != null) {
+                       createMenuItem(menu, descriptor, null);
+               }
+               createDefaultMenuItem(menu, file);
+               new MenuItem(menu, SWT.SEPARATOR);
+               createChooseItem(menu, file);
+       }
+       
+       private IFileStore getFileResource() {
+               if (fFile instanceof IFileStore) {
+                       return (IFileStore) fFile;
+               }
+               return (IFileStore) fFile.getAdapter(IFileStore.class);
+       }
+       
+       private Node getNode() {
+               return (Node) (fFile instanceof Node ? fFile : fFile.getAdapter(Node.class));
+       }
+
+    public boolean isDynamic() {
+               return true;
+       }
+
+    private void openEditor(IEditorDescriptor editor) {
+               IFileStore file = getFileResource();
+               if (file == null) {
+                       return;
+               }
+               try {
+                       String editorId = editor == null ? IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID : editor.getId();
+                       fPage.openEditor(Utils.createEditorInput(file), editorId, true, MATCH_BOTH);
+                       ZipEditorPlugin.getDefault().addFileMonitor(new File(file.toURI()), getNode());
+               } catch (PartInitException e) {
+                       ErrorDialog.openError(fPage.getWorkbenchWindow().getShell(),
+                                       ActionMessages.getString("OpenWithMenu.0"), e.getMessage(), ZipEditorPlugin.createErrorStatus(e.getMessage(), e)); //$NON-NLS-1$
+               }
+       }
+
+       private void openWithProgram(IFileStore file) {
+               ExecutableSelectionDialog dialog = new ExecutableSelectionDialog(
+                               fPage.getWorkbenchWindow().getShell(), previouslySelectedEditor);
+               if (dialog.open() != Window.OK)
+                       return;
+               fFileOpener.openFromOther(file, previouslySelectedEditor = (Editor) dialog.getSelection());
+       }
+
+       private void createDefaultMenuItem(Menu menu, final IFileStore file) {
+               final MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+               menuItem.setText(ActionMessages.getString("OpenWithMenu.1")); //$NON-NLS-1$
+
+               Listener listener = new Listener() {
+                       public void handleEvent(Event event) {
+                               switch (event.type) {
+                               case SWT.Selection:
+                                       if (menuItem.getSelection()) {
+                                               try {
+                                                       fPage.openEditor(Utils.createEditorInput(file), Utils.getEditorId(file),
+                                                                       true, MATCH_BOTH);
+                                                       ZipEditorPlugin.getDefault().addFileMonitor(new File(file.toURI()), getNode());
+                                               } catch (PartInitException e) {
+                                                       ErrorDialog.openError(fPage.getWorkbenchWindow().getShell(),
+                                                                       ActionMessages.getString("OpenWithMenu.2"), e.getMessage(), ZipEditorPlugin.createErrorStatus(e.getMessage(), e)); //$NON-NLS-1$
+                                               }
+                                       }
+                                       break;
+                               }
+                       }
+               };
+
+               menuItem.addListener(SWT.Selection, listener);
+       }
+
+       private void createChooseItem(Menu menu, final IFileStore file) {
+               final MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+               menuItem.setText(ActionMessages.getString("OpenWithMenu.4")); //$NON-NLS-1$
+
+               Listener listener = new Listener() {
+                       public void handleEvent(Event event) {
+                               switch (event.type) {
+                               case SWT.Selection:
+                                       if (menuItem.getSelection()) {
+                                               openWithProgram(file);
+                                       }
+                                       break;
+                               }
+                       }
+               };
+
+               menuItem.addListener(SWT.Selection, listener);
+       }
+
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/PreferencesAction.java b/org.tizen.common.externals/src/zipeditor/actions/PreferencesAction.java
new file mode 100644 (file)
index 0000000..f0c62a5
--- /dev/null
@@ -0,0 +1,119 @@
+package zipeditor.actions;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.ToolItem;
+
+import zipeditor.PreferenceConstants;
+import zipeditor.PreferenceInitializer;
+import zipeditor.ZipEditor;
+import zipeditor.ZipEditorPlugin;
+import zipeditor.model.NodeProperty;
+import zipeditor.model.ZipNodeProperty;
+
+public class PreferencesAction extends EditorAction {
+       private class ColumnAction extends Action {
+               private int fType;
+               private Integer[] fColumnsState;
+
+               private ColumnAction(NodeProperty nodeProperty) {
+                       super(nodeProperty.toString());
+                       fColumnsState = (Integer[]) PreferenceInitializer.split(
+                                       fEditor.getPreferenceStore().getString(PreferenceConstants.VISIBLE_COLUMNS), PreferenceConstants.COLUMNS_SEPARATOR, Integer.class);
+                       setChecked(indexOf(fColumnsState, nodeProperty.getType()) != -1);
+                       fType = nodeProperty.getType();
+               }
+               
+               private int indexOf(Integer[] integers, int type) {
+                       for (int i = 0; i < integers.length; i++) {
+                               if (type == integers[i].intValue())
+                                       return i;
+                       }
+                       return -1;
+               }
+               
+               private Integer[] update(Integer[] integers, boolean set) {
+                       int index = indexOf(integers, fType);
+                       if (set) {
+                               if (index == -1) {
+                                       int size = integers.length;
+                                       System.arraycopy(integers, 0, integers = new Integer[size + 1], 1, size);
+                                       integers[0] = new Integer(fType);
+                               }
+                       } else {
+                               if (index != -1) {
+                                       integers[index] = null;
+                               }
+                       }
+                       return integers;
+               }
+               
+               public void run() {
+                       fEditor.storeTableColumnPreferences();
+                       IPreferenceStore store = fEditor.getPreferenceStore();
+                       fColumnsState = update(fColumnsState, isChecked());
+                       String newValue = PreferenceInitializer.join(fColumnsState, PreferenceConstants.COLUMNS_SEPARATOR);
+                       store.setValue(PreferenceConstants.VISIBLE_COLUMNS, newValue);
+                       fEditor.updateView(fEditor.getMode(), false);
+               }
+       };
+       
+       private MenuManager fMenuManager;
+       
+       public PreferencesAction(ZipEditor editor) {
+               super(ActionMessages.getString("PreferencesAction.0"), editor); //$NON-NLS-1$
+               setToolTipText(ActionMessages.getString("PreferencesAction.1")); //$NON-NLS-1$
+               setImageDescriptor(ZipEditorPlugin.getImageDescriptor("icons/arrow_down.gif")); //$NON-NLS-1$
+       }
+       
+       public void runWithEvent(Event event) {
+               if (fMenuManager == null)
+                       fillMenuManager(fMenuManager = new MenuManager());
+               ToolItem item = (ToolItem) event.widget;
+               Menu menu = fMenuManager.createContextMenu((item.getParent()));
+
+               Rectangle bounds = item.getBounds();
+               Point topLeft = new Point(bounds.x, bounds.y + bounds.height);
+               topLeft = item.getParent().toDisplay(topLeft);
+               menu.setLocation(topLeft.x, topLeft.y);
+               menu.setVisible(true);
+       }
+
+       private void fillMenuManager(MenuManager manager) {
+               MenuManager columns = new MenuManager(ActionMessages.getString("PreferencesAction.2")); //$NON-NLS-1$
+               manager.add(columns);
+               fillColumnsMenu(columns);
+               MenuManager folders = new MenuManager(ActionMessages.getString("PreferencesAction.3")); //$NON-NLS-1$
+               manager.add(folders);
+               fillFoldersMenu(folders);
+               manager.add(new Separator());
+               manager.add(new ToggleStoreFoldersAction(fEditor));
+       }
+
+       private void fillColumnsMenu(MenuManager manager) {
+               manager.add(new ColumnAction(NodeProperty.PNAME));
+               manager.add(new ColumnAction(NodeProperty.PTYPE));
+               manager.add(new ColumnAction(NodeProperty.PDATE));
+               manager.add(new ColumnAction(NodeProperty.PSIZE));
+               manager.add(new ColumnAction(ZipNodeProperty.PPACKED_SIZE));
+               manager.add(new ColumnAction(ZipNodeProperty.PRATIO));
+               manager.add(new ColumnAction(ZipNodeProperty.PCRC));
+               manager.add(new ColumnAction(NodeProperty.PPATH));
+               manager.add(new ColumnAction(ZipNodeProperty.PATTR));
+       }
+       
+       private void fillFoldersMenu(MenuManager manager) {
+               Action foldersVisibleAction = new ToggleViewModeAction(fEditor, ActionMessages.getString("PreferencesAction.4"), PreferenceConstants.PREFIX_EDITOR, PreferenceConstants.VIEW_MODE_FOLDERS_VISIBLE); //$NON-NLS-1$
+               ToggleViewModeAction allInOneLayerAction = new ToggleViewModeAction(fEditor, ActionMessages.getString("PreferencesAction.5"), PreferenceConstants.PREFIX_EDITOR, PreferenceConstants.VIEW_MODE_FOLDERS_ONE_LAYER); //$NON-NLS-1$
+               allInOneLayerAction.setEnabled(foldersVisibleAction.isChecked());
+               
+               manager.add(foldersVisibleAction);
+               manager.add(allInOneLayerAction);
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/RenameNodeAction.java b/org.tizen.common.externals/src/zipeditor/actions/RenameNodeAction.java
new file mode 100644 (file)
index 0000000..237f6c1
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import java.text.MessageFormat;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.TableEditor;
+import org.eclipse.swt.custom.TreeEditor;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.actions.TextActionHandler;
+
+import zipeditor.ZipEditorPlugin;
+import zipeditor.model.Node;
+
+public class RenameNodeAction extends ViewerAction {
+       private TreeEditor fTreeEditor;
+       private TableEditor fTableEditor;
+       private Control fControl;
+       private Text fTextEditor;
+       private Composite fTextEditorParent;
+       private TextActionHandler fTextActionHandler;
+
+       private Node inlinedNode;
+       private boolean saving = false;
+       private String newName;
+       private String[] modelProviderIds;
+
+       public RenameNodeAction(StructuredViewer viewer) {
+               super(ActionMessages.getString("RenameNodeAction.0"), viewer); //$NON-NLS-1$
+               setToolTipText(ActionMessages.getString("RenameNodeAction.1")); //$NON-NLS-1$
+               setId(ZipEditorPlugin.PLUGIN_ID + ".RenameAction"); //$NON-NLS-1$
+
+               fControl = viewer.getControl();
+               if (fControl instanceof Tree) {
+                       fTreeEditor = new TreeEditor((Tree) fControl);
+               } else if (fControl instanceof Table) {
+                       fTableEditor = new TableEditor((Table) fControl);
+               } else {
+                       throw new IllegalArgumentException();
+               }
+       }
+
+       private boolean checkOverwrite(final Shell shell, final Node destination) {
+
+               final boolean[] result = new boolean[1];
+
+               Runnable query = new Runnable() {
+                       public void run() {
+                               String message = ActionMessages.getString("RenameNodeAction.2"); //$NON-NLS-1$
+                               String title = ActionMessages.getString("RenameNodeAction.3"); //$NON-NLS-1$
+                               result[0] = MessageDialog.openQuestion(shell,
+                                               title, MessageFormat.format(message,
+                                                               new Object[] { destination.getName() }));
+                       }
+
+               };
+
+               shell.getDisplay().syncExec(query);
+               return result[0];
+       }
+
+       Composite createParent() {
+               Composite result = new Composite((Composite) fControl, SWT.NONE);
+               if (fControl instanceof Tree) {
+                       TreeItem[] selectedItems = ((Tree) fControl).getSelection();
+                       fTreeEditor.horizontalAlignment = SWT.LEFT;
+                       fTreeEditor.grabHorizontal = true;
+                       fTreeEditor.setEditor(result, selectedItems[0]);
+               } else {
+                       TableItem[] selectedItems = ((Table) fControl).getSelection();
+                       fTableEditor.horizontalAlignment = SWT.LEFT;
+                       fTableEditor.grabHorizontal = true;
+                       fTableEditor.setEditor(result, selectedItems[0], 0);
+               }
+               return result;
+       }
+
+       private void createTextEditor(final Node node) {
+               // Create text editor parent. This draws a nice bounding rect.
+               fTextEditorParent = createParent();
+               fTextEditorParent.setVisible(false);
+               final int inset = 1;
+               if (inset > 0) {
+                       fTextEditorParent.addListener(SWT.Paint, new Listener() {
+                               public void handleEvent(Event e) {
+                                       Point textSize = fTextEditor.getSize();
+                                       Point parentSize = fTextEditorParent.getSize();
+                                       e.gc.drawRectangle(0, 0, Math.min(textSize.x + 4,
+                                                       parentSize.x - 1), parentSize.y - 1);
+                               }
+                       });
+               }
+               // Create inner text editor.
+               fTextEditor = new Text(fTextEditorParent, SWT.NONE);
+               fTextEditor.setFont(fControl.getFont());
+               fTextEditorParent.setBackground(fTextEditor.getBackground());
+               fTextEditor.addListener(SWT.Modify, new Listener() {
+                       public void handleEvent(Event e) {
+                               Point textSize = fTextEditor.computeSize(SWT.DEFAULT,
+                                               SWT.DEFAULT);
+                               textSize.x += textSize.y; // Add extra space for new
+                               // characters.
+                               Point parentSize = fTextEditorParent.getSize();
+                               fTextEditor.setBounds(2, inset, Math.min(textSize.x,
+                                               parentSize.x - 4), parentSize.y - 2 * inset);
+                               fTextEditorParent.redraw();
+                       }
+               });
+               fTextEditor.addListener(SWT.Traverse, new Listener() {
+                       public void handleEvent(Event event) {
+
+                               switch (event.detail) {
+                               case SWT.TRAVERSE_ESCAPE:
+                                       // Do nothing in this case
+                                       disposeTextWidget();
+                                       event.doit = true;
+                                       event.detail = SWT.TRAVERSE_NONE;
+                                       break;
+                               case SWT.TRAVERSE_RETURN:
+                                       saveChangesAndDispose(node);
+                                       event.doit = true;
+                                       event.detail = SWT.TRAVERSE_NONE;
+                                       break;
+                               }
+                       }
+               });
+               fTextEditor.addFocusListener(new FocusAdapter() {
+                       public void focusLost(FocusEvent fe) {
+                               saveChangesAndDispose(node);
+                       }
+               });
+
+               if (fTextActionHandler != null) {
+                       fTextActionHandler.addText(fTextEditor);
+               }
+       }
+
+       private void disposeTextWidget() {
+               if (fTextActionHandler != null) {
+                       fTextActionHandler.removeText(fTextEditor);
+               }
+
+               if (fTextEditorParent != null) {
+                       fTextEditorParent.dispose();
+                       fTextEditorParent = null;
+                       fTextEditor = null;
+                       if (fTreeEditor != null)
+                               fTreeEditor.setEditor(null, null);
+                       else
+                               fTableEditor.setEditor(null, null, 0);
+               }
+       }
+
+       private void queryNewNodeNameInline(final Node node) {
+               if (node == null)
+                       return;
+               if (fTextEditorParent == null) {
+                       createTextEditor(node);
+               }
+               fTextEditor.setText(node.getName());
+
+               // Open text editor with initial size.
+               fTextEditorParent.setVisible(true);
+               Point textSize = fTextEditor.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+               textSize.x += textSize.y; // Add extra space for new characters.
+               Point parentSize = fTextEditorParent.getSize();
+               int inset = 1;
+               fTextEditor.setBounds(2, inset, Math.min(textSize.x, parentSize.x - 4),
+                               parentSize.y - 2 * inset);
+               fTextEditorParent.redraw();
+               fTextEditor.selectAll();
+               fTextEditor.setFocus();
+       }
+
+       public void run() {
+               Node[] nodes = getSelectedNodes();
+               if (nodes.length == 1)
+                       queryNewNodeNameInline(nodes[0]);
+       }
+
+       private Node getSelectedNode() {
+               Node[] nodes = getSelectedNodes();
+               return nodes.length > 0 ? nodes[0] : null;
+       }
+
+       protected void runWithNewName(String name) {
+               this.newName = name;
+               doOperation();
+       }
+
+       private void saveChangesAndDispose(Node node) {
+               if (saving == true) {
+                       return;
+               }
+
+               saving = true;
+               inlinedNode = node;
+               final String newName = fTextEditor.getText();
+               Runnable query = new Runnable() {
+                       public void run() {
+                               try {
+                                       if (!newName.equals(inlinedNode.getName())) {
+                                               runWithNewName(newName);
+                                       }
+                                       inlinedNode = null;
+                                       disposeTextWidget();
+                                       if (fControl != null && !fControl.isDisposed()) {
+                                               fControl.setFocus();
+                                       }
+                               } finally {
+                                       saving = false;
+                               }
+                       }
+               };
+               fControl.getDisplay().asyncExec(query);
+       }
+
+       public void setTextActionHandler(TextActionHandler actionHandler) {
+               fTextActionHandler = actionHandler;
+       }
+
+       public String[] getModelProviderIds() {
+               return modelProviderIds;
+       }
+
+       public void setModelProviderIds(String[] modelProviderIds) {
+               this.modelProviderIds = modelProviderIds;
+       }
+
+       protected void doOperation() {
+               Node node = getSelectedNode();
+               if (node == null)
+                       return;
+               Node newNode = newName != null ? node.getParent().getChildByName(newName, false) : null;
+               boolean go = true;
+               if (newNode != null) {
+                       go = checkOverwrite(fControl.getShell(), newNode);
+               }
+               if (go) {
+                       node.setName(newName);
+               }
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/ReverseSelectionAction.java b/org.tizen.common.externals/src/zipeditor/actions/ReverseSelectionAction.java
new file mode 100644 (file)
index 0000000..ffdcad3
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * (c) Copyright 2002, 2013 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+
+import zipeditor.model.Node;
+
+public class ReverseSelectionAction extends ViewerAction {
+
+       public static final String ID = "zipeditor.command.reverseSelection"; //$NON-NLS-1$
+
+       public ReverseSelectionAction(StructuredViewer viewer) {
+               super(ActionMessages.getString("ReverseSelectionAction_0"), viewer); //$NON-NLS-1$
+               setId(ID);
+               setActionDefinitionId(ID);
+       }
+
+       public void run() {
+               Object root = getViewer().getInput();
+               if (root instanceof Node) {
+                       Set selection = new HashSet(((StructuredSelection) getViewer().getSelection()).toList());
+                       List newSelection = new ArrayList();
+                       reverseSelection((Node) root, selection, newSelection);
+                       getViewer().setSelection(new StructuredSelection(newSelection));
+               }
+       }
+
+       private void reverseSelection(Node node, Set selection, List newSelection) {
+               Node[] children = node.getChildren();
+               for (int i = 0; i < children.length; i++) {
+                       Node child = children[i];
+                       if (!selection.contains(child))
+                               newSelection.add(child);
+                       reverseSelection(child, selection, newSelection);                       
+               }
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/RevertAction.java b/org.tizen.common.externals/src/zipeditor/actions/RevertAction.java
new file mode 100644 (file)
index 0000000..0f0c894
--- /dev/null
@@ -0,0 +1,13 @@
+package zipeditor.actions;
+
+import zipeditor.ZipEditor;
+
+public class RevertAction extends EditorAction {
+       public RevertAction(ZipEditor editor) {
+               super(ActionMessages.getString("RevertAction.0"), editor); //$NON-NLS-1$
+       }
+
+       public void run() {
+               fEditor.doRevert();
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/SaveAction.java b/org.tizen.common.externals/src/zipeditor/actions/SaveAction.java
new file mode 100644 (file)
index 0000000..099e33e
--- /dev/null
@@ -0,0 +1,28 @@
+package zipeditor.actions;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+
+import zipeditor.ZipEditor;
+import zipeditor.ZipEditorPlugin;
+
+public class SaveAction extends EditorAction {
+       public SaveAction(ZipEditor editor) {
+               super(ActionMessages.getString("SaveAction.0"), editor); //$NON-NLS-1$
+       }
+
+       public void run() {
+               IRunnableWithProgress op = new IRunnableWithProgress() {
+                       public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+                               fEditor.doSave(monitor);
+                       }
+               };
+               try {
+                       fEditor.getSite().getWorkbenchWindow().run(true, true, op);
+               } catch (Exception e) {
+                       ZipEditorPlugin.log(e);
+               }
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/SelectAllAction.java b/org.tizen.common.externals/src/zipeditor/actions/SelectAllAction.java
new file mode 100644 (file)
index 0000000..a742ff1
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+
+public class SelectAllAction extends ViewerAction {
+       public SelectAllAction(StructuredViewer viewer) {
+               super(ActionMessages.getString("SelectAllAction.0"), viewer); //$NON-NLS-1$
+       }
+
+       public void run() {
+               StructuredViewer viewer = getViewer();
+               if (viewer instanceof TreeViewer)
+                       ((TreeViewer) viewer).getTree().selectAll();
+               else if (viewer instanceof TableViewer)
+                       ((TableViewer) viewer).getTable().selectAll();
+               viewer.setSelection(viewer.getSelection());
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/SelectPatternAction.java b/org.tizen.common.externals/src/zipeditor/actions/SelectPatternAction.java
new file mode 100644 (file)
index 0000000..fff0ea4
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * (c) Copyright 2002, 2013 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.window.Window;
+
+import zipeditor.model.Node;
+
+public class SelectPatternAction extends ViewerAction {
+
+       public static final String ID = "zipeditor.command.selectPattern"; //$NON-NLS-1$
+
+       private String fPreviousValue;
+
+       public SelectPatternAction(StructuredViewer viewer) {
+               super(ActionMessages.getString("SelectPatternAction.0"), viewer); //$NON-NLS-1$
+               setId(ID);
+               setActionDefinitionId(ID);
+       }
+
+       public void run() {
+               InputDialog dlg = new InputDialog(getViewer().getControl().getShell(), ActionMessages.getString("SelectPatternAction.1"), ActionMessages.getString("SelectPatternAction.2"), //$NON-NLS-1$ //$NON-NLS-2$
+                               fPreviousValue, null);
+               if (dlg.open() != Window.OK)
+                       return;
+               String value = dlg.getValue();
+               if (value != null) {
+                       Object root = getViewer().getInput();
+                       if (root instanceof Node) {
+                               List selection = new ArrayList();
+                               StringMatcher matcher = new StringMatcher(value, true, false);
+                               collectMatches((Node) root, matcher, selection);
+                               getViewer().setSelection(new StructuredSelection(selection));
+                       }
+                       fPreviousValue = value;
+               }
+       }
+
+       private void collectMatches(Node node, StringMatcher matcher, List selection) {
+               Node[] children = node.getChildren();
+               for (int i = 0; i < children.length; i++) {
+                       Node child = children[i];
+                       if (matcher.match(child.getName()))
+                               selection.add(child);
+                       collectMatches(child, matcher, selection);                      
+               }
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/SortAction.java b/org.tizen.common.externals/src/zipeditor/actions/SortAction.java
new file mode 100644 (file)
index 0000000..1ee8d1f
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.viewers.StructuredViewer;
+
+import zipeditor.PreferenceConstants;
+import zipeditor.ZipEditorPlugin;
+import zipeditor.ZipSorter;
+
+public class SortAction extends ViewerAction {
+       private String fPreferenceKey;
+       
+       public final static String SORTING_CHANGED = "sorting_changed"; //$NON-NLS-1$
+
+       public SortAction(StructuredViewer viewer, String preferencePrefix) {
+               super(ActionMessages.getString("SortAction.0"), viewer); //$NON-NLS-1$
+               setToolTipText(ActionMessages.getString("SortAction.1")); //$NON-NLS-1$
+               setImageDescriptor(ZipEditorPlugin.getImageDescriptor("icons/alphab_sort_co.gif")); //$NON-NLS-1$
+               fPreferenceKey = preferencePrefix + PreferenceConstants.SORT_ENABLED;
+               setChecked(ZipEditorPlugin.getDefault().getPreferenceStore().getBoolean(fPreferenceKey));
+       }
+
+       public void run() {
+               IPreferenceStore store = ZipEditorPlugin.getDefault().getPreferenceStore();
+               store.setValue(fPreferenceKey, !store.getBoolean(fPreferenceKey));
+               ((ZipSorter) getViewer().getSorter()).update();
+
+               refreshViewer();
+               
+               store.firePropertyChangeEvent(fPreferenceKey + SORTING_CHANGED, null, null);
+       }
+
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/StringMatcher.java b/org.tizen.common.externals/src/zipeditor/actions/StringMatcher.java
new file mode 100644 (file)
index 0000000..9a86422
--- /dev/null
@@ -0,0 +1,448 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package zipeditor.actions;
+
+import java.util.Vector;
+
+/**
+ * A string pattern matcher suppporting &#39;*&#39; and &#39;&#63;&#39; wildcards.
+ */
+public class StringMatcher {
+    protected String fPattern;
+
+    protected int fLength; // pattern length
+
+    protected boolean fIgnoreWildCards;
+
+    protected boolean fIgnoreCase;
+
+    protected boolean fHasLeadingStar;
+
+    protected boolean fHasTrailingStar;
+
+    protected String fSegments[]; //the given pattern is split into * separated segments
+
+    /* boundary value beyond which we don't need to search in the text */
+    protected int fBound = 0;
+
+    protected static final char fSingleWildCard = '\u0000';
+
+    public static class Position {
+        int start; //inclusive
+
+        int end; //exclusive
+
+        public Position(int start, int end) {
+            this.start = start;
+            this.end = end;
+        }
+
+        public int getStart() {
+            return start;
+        }
+
+        public int getEnd() {
+            return end;
+        }
+    }
+
+    /**
+     * StringMatcher constructor takes in a String object that is a simple 
+     * pattern which may contain &#39*&#39 for 0 and many characters and
+     * &#39;&#63;&#39; for exactly one character.  
+     *
+     * Literal &#39;*&#39; and &#39;*&#39; characters must be escaped in the pattern 
+     * e.g. &quot;&#92;*&quot; means literal &quot;*&quot;, etc.
+     *
+     * Escaping any other character (including the escape character itself), 
+     * just results in that character in the pattern.
+     * e.g. &quot;&#92;a&quot; means &quot;a&quot; and &quot;&#92;&#92;&quot; means &quot;&#92;&quot;
+     *
+     * If invoking the StringMatcher with string literals in Java, don't forget
+     * escape characters are represented by &quot;&#92;&#92;&quot;.
+     *
+     * @param pattern the pattern to match text against
+     * @param ignoreCase if true, case is ignored
+     * @param ignoreWildCards if true, wild cards and their escape sequences are ignored
+     *                   (everything is taken literally).
+     */
+    public StringMatcher(String pattern, boolean ignoreCase,
+            boolean ignoreWildCards) {
+        if (pattern == null) {
+                       throw new IllegalArgumentException();
+               }
+        fIgnoreCase = ignoreCase;
+        fIgnoreWildCards = ignoreWildCards;
+        fPattern = pattern;
+        fLength = pattern.length();
+
+        if (fIgnoreWildCards) {
+            parseNoWildCards();
+        } else {
+            parseWildCards();
+        }
+    }
+
+    /**
+     * Find the first occurrence of the pattern between <code>start</code)(inclusive) 
+     * and <code>end</code>(exclusive).  
+     * @param text  the String object to search in 
+     * @param start  the starting index of the search range, inclusive
+     * @param end  the ending index of the search range, exclusive
+     * @return an <code>StringMatcher.Position</code> object that keeps the starting 
+     * (inclusive) and ending positions (exclusive) of the first occurrence of the 
+     * pattern in the specified range of the text; return null if not found or subtext
+     * is empty (start==end). A pair of zeros is returned if pattern is empty string
+     * Note that for pattern like &quot;*abc*&quot; with leading and trailing stars, position of &quot;abc&quot;
+     * is returned. For a pattern like&quot;*&#63;&#63;*&quot; in text &quot;abcdf&quot;, (1,3) is returned
+     */
+    public StringMatcher.Position find(String text, int start, int end) {
+        if (text == null) {
+                       throw new IllegalArgumentException();
+               }
+
+        int tlen = text.length();
+        if (start < 0) {
+                       start = 0;
+               }
+        if (end > tlen) {
+                       end = tlen;
+               }
+        if (end < 0 || start >= end) {
+                       return null;
+               }
+        if (fLength == 0) {
+                       return new Position(start, start);
+               }
+        if (fIgnoreWildCards) {
+            int x = posIn(text, start, end);
+            if (x < 0) {
+                               return null;
+                       }
+            return new Position(x, x + fLength);
+        }
+
+        int segCount = fSegments.length;
+        if (segCount == 0) {
+                       return new Position(start, end);
+               }
+
+        int curPos = start;
+        int matchStart = -1;
+        int i;
+        for (i = 0; i < segCount && curPos < end; ++i) {
+            String current = fSegments[i];
+            int nextMatch = regExpPosIn(text, curPos, end, current);
+            if (nextMatch < 0) {
+                               return null;
+                       }
+            if (i == 0) {
+                               matchStart = nextMatch;
+                       }
+            curPos = nextMatch + current.length();
+        }
+        if (i < segCount) {
+                       return null;
+               }
+        return new Position(matchStart, curPos);
+    }
+
+    /**
+     * match the given <code>text</code> with the pattern 
+     * @return true if matched eitherwise false
+     * @param text  a String object 
+     */
+    public boolean match(String text) {
+        return match(text, 0, text.length());
+    }
+
+    /**
+     * Given the starting (inclusive) and the ending (exclusive) positions in the   
+     * <code>text</code>, determine if the given substring matches with aPattern  
+     * @return true if the specified portion of the text matches the pattern
+     * @param text  a <code>String</code> object that contains the substring to match 
+     * @param start  marks the starting position (inclusive) of the substring
+     * @param end  marks the ending index (exclusive) of the substring 
+     */
+    public boolean match(String text, int start, int end) {
+        if (null == text) {
+                       throw new IllegalArgumentException();
+               }
+
+        if (start > end) {
+                       return false;
+               }
+
+        if (fIgnoreWildCards) {
+                       return (end - start == fLength)
+                    && fPattern.regionMatches(fIgnoreCase, 0, text, start,
+                            fLength);
+               }
+        int segCount = fSegments.length;
+        if (segCount == 0 && (fHasLeadingStar || fHasTrailingStar)) {
+                       return true;
+               }
+        if (start == end) {
+                       return fLength == 0;
+               }
+        if (fLength == 0) {
+                       return start == end;
+               }
+
+        int tlen = text.length();
+        if (start < 0) {
+                       start = 0;
+               }
+        if (end > tlen) {
+                       end = tlen;
+               }
+
+        int tCurPos = start;
+        int bound = end - fBound;
+        if (bound < 0) {
+                       return false;
+               }
+        int i = 0;
+        String current = fSegments[i];
+        int segLength = current.length();
+
+        /* process first segment */
+        if (!fHasLeadingStar) {
+            if (!regExpRegionMatches(text, start, current, 0, segLength)) {
+                return false;
+            } else {
+                ++i;
+                tCurPos = tCurPos + segLength;
+            }
+        }
+        if ((fSegments.length == 1) && (!fHasLeadingStar)
+                && (!fHasTrailingStar)) {
+            // only one segment to match, no wildcards specified
+            return tCurPos == end;
+        }
+        /* process middle segments */
+        while (i < segCount) {
+            current = fSegments[i];
+            int currentMatch;
+            int k = current.indexOf(fSingleWildCard);
+            if (k < 0) {
+                currentMatch = textPosIn(text, tCurPos, end, current);
+                if (currentMatch < 0) {
+                                       return false;
+                               }
+            } else {
+                currentMatch = regExpPosIn(text, tCurPos, end, current);
+                if (currentMatch < 0) {
+                                       return false;
+                               }
+            }
+            tCurPos = currentMatch + current.length();
+            i++;
+        }
+
+        /* process final segment */
+        if (!fHasTrailingStar && tCurPos != end) {
+            int clen = current.length();
+            return regExpRegionMatches(text, end - clen, current, 0, clen);
+        }
+        return i == segCount;
+    }
+
+    /**
+     * This method parses the given pattern into segments seperated by wildcard '*' characters.
+     * Since wildcards are not being used in this case, the pattern consists of a single segment.
+     */
+    private void parseNoWildCards() {
+        fSegments = new String[1];
+        fSegments[0] = fPattern;
+        fBound = fLength;
+    }
+
+    /**
+     * Parses the given pattern into segments seperated by wildcard &#39;*&#39; characters.
+     * @param p, a String object that is a simple regular expression with ?*? and/or &#39;&#63;&#39;
+     */
+    private void parseWildCards() {
+        if (fPattern.startsWith("*")) { //$NON-NLS-1$
+                       fHasLeadingStar = true;
+               }
+        if (fPattern.endsWith("*")) {//$NON-NLS-1$
+            /* make sure it's not an escaped wildcard */
+            if (fLength > 1 && fPattern.charAt(fLength - 2) != '\\') {
+                fHasTrailingStar = true;
+            }
+        }
+
+        Vector temp = new Vector();
+
+        int pos = 0;
+        StringBuffer buf = new StringBuffer();
+        while (pos < fLength) {
+            char c = fPattern.charAt(pos++);
+            switch (c) {
+            case '\\':
+                if (pos >= fLength) {
+                    buf.append(c);
+                } else {
+                    char next = fPattern.charAt(pos++);
+                    /* if it's an escape sequence */
+                    if (next == '*' || next == '?' || next == '\\') {
+                        buf.append(next);
+                    } else {
+                        /* not an escape sequence, just insert literally */
+                        buf.append(c);
+                        buf.append(next);
+                    }
+                }
+                break;
+            case '*':
+                if (buf.length() > 0) {
+                    /* new segment */
+                    temp.addElement(buf.toString());
+                    fBound += buf.length();
+                    buf.setLength(0);
+                }
+                break;
+            case '?':
+                /* append special character representing single match wildcard */
+                buf.append(fSingleWildCard);
+                break;
+            default:
+                buf.append(c);
+            }
+        }
+
+        /* add last buffer to segment list */
+        if (buf.length() > 0) {
+            temp.addElement(buf.toString());
+            fBound += buf.length();
+        }
+
+        fSegments = new String[temp.size()];
+        temp.copyInto(fSegments);
+    }
+
+    /** 
+     * @param text  a string which contains no wildcard
+     * @param start  the starting index in the text for search, inclusive
+     * @param end  the stopping point of search, exclusive
+     * @return the starting index in the text of the pattern , or -1 if not found 
+     */
+    protected int posIn(String text, int start, int end) {//no wild card in pattern
+        int max = end - fLength;
+
+        if (!fIgnoreCase) {
+            int i = text.indexOf(fPattern, start);
+            if (i == -1 || i > max) {
+                               return -1;
+                       }
+            return i;
+        }
+
+        for (int i = start; i <= max; ++i) {
+            if (text.regionMatches(true, i, fPattern, 0, fLength)) {
+                               return i;
+                       }
+        }
+
+        return -1;
+    }
+
+    /** 
+     * @param text  a simple regular expression that may only contain '&#63;'(s)
+     * @param start  the starting index in the text for search, inclusive
+     * @param end  the stopping point of search, exclusive
+     * @param p  a simple regular expression that may contains '&#63;'
+     * @return the starting index in the text of the pattern , or -1 if not found 
+     */
+    protected int regExpPosIn(String text, int start, int end, String p) {
+        int plen = p.length();
+
+        int max = end - plen;
+        for (int i = start; i <= max; ++i) {
+            if (regExpRegionMatches(text, i, p, 0, plen)) {
+                               return i;
+                       }
+        }
+        return -1;
+    }
+
+    /**
+     * 
+     * @return boolean
+     * @param  text  a String to match
+     * @param tStart  int that indicates the starting index of match, inclusive
+     * @param p  String,  String, a simple regular expression that may contain '&#63;'
+     * @param pStart
+     * @param plen     
+     */
+    protected boolean regExpRegionMatches(String text, int tStart, String p,
+            int pStart, int plen) {
+        while (plen-- > 0) {
+            char tchar = text.charAt(tStart++);
+            char pchar = p.charAt(pStart++);
+
+            /* process wild cards */
+            if (!fIgnoreWildCards) {
+                /* skip single wild cards */
+                if (pchar == fSingleWildCard) {
+                    continue;
+                }
+            }
+            if (pchar == tchar) {
+                               continue;
+                       }
+            if (fIgnoreCase) {
+                if (Character.toUpperCase(tchar) == Character
+                        .toUpperCase(pchar)) {
+                                       continue;
+                               }
+                // comparing after converting to upper case doesn't handle all cases;
+                // also compare after converting to lower case
+                if (Character.toLowerCase(tchar) == Character
+                        .toLowerCase(pchar)) {
+                                       continue;
+                               }
+            }
+            return false;
+        }
+        return true;
+    }
+
+    /** 
+     * @param text  the string to match
+     * @param start  the starting index in the text for search, inclusive
+     * @param end  the stopping point of search, exclusive
+     * @param p  a string that has no wildcard
+     * @return the starting index in the text of the pattern , or -1 if not found 
+     */
+    protected int textPosIn(String text, int start, int end, String p) {
+
+        int plen = p.length();
+        int max = end - plen;
+
+        if (!fIgnoreCase) {
+            int i = text.indexOf(p, start);
+            if (i == -1 || i > max) {
+                               return -1;
+                       }
+            return i;
+        }
+
+        for (int i = start; i <= max; ++i) {
+            if (text.regionMatches(true, i, p, 0, plen)) {
+                               return i;
+                       }
+        }
+
+        return -1;
+    }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/TogglePreferenceAction.java b/org.tizen.common.externals/src/zipeditor/actions/TogglePreferenceAction.java
new file mode 100644 (file)
index 0000000..bd4629e
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+public class TogglePreferenceAction extends Action {
+       private String fPreferenceKey;
+       private IPreferenceStore fStore;
+
+       public TogglePreferenceAction(String text, String preferenceKey, IPreferenceStore store) {
+               super(text);
+               fPreferenceKey = preferenceKey;
+               setChecked(store.getBoolean(fPreferenceKey));
+               fStore = store;
+       }
+
+       public void run() {
+               togglePreference();
+       }
+
+       protected void togglePreference() {
+               fStore.setValue(fPreferenceKey, !fStore.getBoolean(fPreferenceKey));
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/ToggleStoreFoldersAction.java b/org.tizen.common.externals/src/zipeditor/actions/ToggleStoreFoldersAction.java
new file mode 100644 (file)
index 0000000..dd3fe75
--- /dev/null
@@ -0,0 +1,17 @@
+package zipeditor.actions;
+
+import zipeditor.PreferenceConstants;
+import zipeditor.ZipEditor;
+
+public class ToggleStoreFoldersAction extends EditorAction {
+
+       protected ToggleStoreFoldersAction(ZipEditor editor) {
+               super(ActionMessages.getString("PreferencesAction.6"), editor); //$NON-NLS-1$
+               setChecked(editor.getRootNode().getModel().isStoreFolders());
+       }
+
+       public void run() {
+               fEditor.getRootNode().getModel().setStoreFolders(isChecked());
+               fEditor.getPreferenceStore().setValue(PreferenceConstants.STORE_FOLDERS_IN_ARCHIVES, isChecked());
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/ToggleViewModeAction.java b/org.tizen.common.externals/src/zipeditor/actions/ToggleViewModeAction.java
new file mode 100644 (file)
index 0000000..0e53a3e
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import zipeditor.PreferenceConstants;
+import zipeditor.ZipEditor;
+
+public class ToggleViewModeAction extends EditorAction {
+       private String fPreferenceKey;
+       private int fModeConstant;
+       private int fMode;
+
+       public ToggleViewModeAction(ZipEditor editor, String text, String preferencePrefix, int modeConstant) {
+               super(text, editor);
+
+               fPreferenceKey = preferencePrefix + PreferenceConstants.VIEW_MODE;
+               fModeConstant = modeConstant;
+               
+               fMode = editor.getPreferenceStore().getInt(fPreferenceKey);
+               checkDependencies();
+               setChecked((fMode & fModeConstant) > 0);
+       }
+
+       public void run() {
+               fMode = (fMode & (fModeConstant ^ -1)) | (isChecked() ? fModeConstant : 0);
+               checkDependencies();
+               fEditor.getPreferenceStore().setValue(fPreferenceKey, fMode);
+               fEditor.updateView(fMode, true);
+       }
+
+       private void checkDependencies() {
+               boolean foldersVisible = (fMode & PreferenceConstants.VIEW_MODE_FOLDERS_VISIBLE) > 0;
+               boolean allInOneLayer = (fMode & PreferenceConstants.VIEW_MODE_FOLDERS_ONE_LAYER) > 0;
+               if (!foldersVisible && !allInOneLayer)
+                       fMode |= PreferenceConstants.VIEW_MODE_FOLDERS_ONE_LAYER;
+               
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/ViewerAction.java b/org.tizen.common.externals/src/zipeditor/actions/ViewerAction.java
new file mode 100644 (file)
index 0000000..ded7275
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+
+import zipeditor.Utils;
+import zipeditor.model.Node;
+
+public abstract class ViewerAction extends Action {
+       private StructuredViewer fViewer;
+
+       public ViewerAction(String text, StructuredViewer viewer) {
+               super(text);
+               Assert.isNotNull(viewer);
+               fViewer = viewer;
+       }
+       
+       public StructuredViewer getViewer() {
+               return fViewer;
+       }
+       
+       protected Node[] getSelectedNodes() {
+               return Utils.getSelectedNodes(getSelection());
+       }
+       
+       protected Node getViewerInputAsNode() {
+               return (Node) fViewer.getInput();
+       }
+
+       protected void refreshViewer() {
+               if (fViewer.getControl() == null || fViewer.getControl().isDisposed())
+                       return;
+               fViewer.getControl().setRedraw(false);
+               fViewer.refresh();
+               fViewer.getControl().setRedraw(true);
+       }
+
+       protected ISelection getSelection() {
+               return fViewer.getSelection();
+       }
+}
\ No newline at end of file
diff --git a/org.tizen.common.externals/src/zipeditor/actions/ZipActionGroup.java b/org.tizen.common.externals/src/zipeditor/actions/ZipActionGroup.java
new file mode 100644 (file)
index 0000000..70764df
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IWorkbenchCommandConstants;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.actions.ActionGroup;
+
+import zipeditor.PreferenceConstants;
+import zipeditor.ZipEditor;
+
+public class ZipActionGroup extends ActionGroup {
+       private IAction fAddAction;
+       private IAction fCopyAction;
+       private IAction fCopyQualifiedAction;
+       private IAction fDeleteAction;
+       private IAction fExtractAction;
+       private IAction fSortAction;
+       private IAction fSaveAction;
+       private IAction fRevertAction;
+       private IAction fPreferencesAction;
+       private IAction fPropertiesAction;
+       private ZipEditor fEditor;
+       private Clipboard fClipboard;
+       
+       public ZipActionGroup(ZipEditor editor) {
+               fRevertAction = new RevertAction(editor);
+               fRevertAction.setActionDefinitionId(IWorkbenchCommandConstants.FILE_REVERT);
+               fSaveAction = new SaveAction(editor);
+               fSaveAction.setActionDefinitionId(IWorkbenchCommandConstants.FILE_SAVE);
+               fPreferencesAction = new PreferencesAction(editor);
+
+               fEditor = editor;
+               fClipboard = new Clipboard(fEditor.getViewer().getControl().getDisplay());
+       }
+       
+       public void fillContextMenu(IMenuManager menu) {
+               lazilyCreateActions();
+               menu.add(new Separator());
+               menu.add(fCopyAction);
+               menu.add(fCopyQualifiedAction);
+               menu.add(fDeleteAction);
+               menu.add(new Separator());
+               menu.add(fSaveAction);
+               menu.add(fRevertAction);
+               menu.add(new Separator());
+               menu.add(fAddAction);
+               menu.add(fExtractAction);
+               menu.add(new Separator());
+               menu.add(fPropertiesAction);
+               
+               updateActionBars();
+       }
+       
+    private void lazilyCreateActions() {
+               if (fPropertiesAction == null) {
+                       fPropertiesAction = new MultiPropertyDialogAction(fEditor.getSite(), fEditor.getViewer());
+                       fPropertiesAction.setActionDefinitionId(IWorkbenchCommandConstants.FILE_PROPERTIES);
+               }
+               if (fAddAction == null)
+                       fAddAction = new AddAction(fEditor.getViewer());
+               if (fExtractAction == null)
+                       fExtractAction = new ExtractAction(fEditor.getViewer());
+               if (fCopyAction == null) {
+                       fCopyAction = new CopyAction(fEditor.getViewer(), false, fClipboard);
+                       fCopyAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_COPY);
+               }
+               if (fCopyQualifiedAction == null)
+                       fCopyQualifiedAction = new CopyAction(fEditor.getViewer(), true, fClipboard);
+               if (fDeleteAction == null) {
+                       fDeleteAction = new DeleteAction(fEditor.getViewer());
+                       fDeleteAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_DELETE);
+               }
+               if (fSortAction == null)
+                       fSortAction = new SortAction(fEditor.getViewer(), PreferenceConstants.PREFIX_EDITOR);
+       }
+
+       public void fillToolBarManager(IToolBarManager manager, int mode) {
+               lazilyCreateActions();
+               manager.add(new Separator());
+               manager.add(fAddAction);
+               manager.add(fExtractAction);
+               manager.add(new Separator());
+               manager.add(fDeleteAction);
+               manager.add(new Separator());
+               manager.add(fSortAction);
+               if ((mode & PreferenceConstants.VIEW_MODE_TREE) == 0) {
+                       manager.add(new Separator());
+                       manager.add(fPreferencesAction);
+               }
+       }
+    
+    public void fillActionBars(IActionBars actionBars) {
+               lazilyCreateActions();
+
+               actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), fCopyAction);
+               actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), fDeleteAction);
+               actionBars.setGlobalActionHandler(ActionFactory.SAVE.getId(), fSaveAction);
+               actionBars.setGlobalActionHandler(ActionFactory.REVERT.getId(), fRevertAction);
+               actionBars.setGlobalActionHandler(ActionFactory.PROPERTIES.getId(), fPropertiesAction);
+               updateActionBars();
+    }
+       
+       public void updateActionBars() {
+               if (getContext() == null)
+                       return;
+               IStructuredSelection selection = (IStructuredSelection) getContext().getSelection();
+               boolean empty = selection.isEmpty();
+               
+               lazilyCreateActions();
+               fCopyAction.setEnabled(!empty);
+               fCopyQualifiedAction.setEnabled(!empty);
+               fDeleteAction.setEnabled(!empty);
+               fSaveAction.setEnabled(fEditor.isDirty());
+               fRevertAction.setEnabled(fEditor.isDirty());
+               fPropertiesAction.setEnabled(!empty);
+       }
+       
+       public void dispose() {
+               super.dispose();
+               fClipboard.dispose();
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/actions/ZipActionProvider.java b/org.tizen.common.externals/src/zipeditor/actions/ZipActionProvider.java
new file mode 100644 (file)
index 0000000..dfbe10f
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * (c) Copyright 2006 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.actions;
+
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.navigator.CommonActionProvider;
+import org.eclipse.ui.navigator.ICommonActionExtensionSite;
+
+public class ZipActionProvider extends CommonActionProvider {
+       private OpenActionGroup fOpenActionGroup;
+       private ViewerAction fExtractAction;
+       private IAction fPropertiesAction;
+       
+       public void init(ICommonActionExtensionSite aSite) {
+               super.init(aSite);
+               fOpenActionGroup = new OpenActionGroup(aSite.getStructuredViewer(), true);
+               fExtractAction = new ExtractAction(aSite.getStructuredViewer());
+       }
+       
+       public void dispose() {
+               super.dispose();
+               fOpenActionGroup.dispose();
+       }
+
+       public void fillContextMenu(IMenuManager menu) {
+               fOpenActionGroup.setContext(getContext());
+               fOpenActionGroup.fillContextMenu(menu);
+               menu.appendToGroup(IWorkbenchActionConstants.MB_ADDITIONS, new Separator());
+               menu.appendToGroup(IWorkbenchActionConstants.MB_ADDITIONS, fExtractAction);
+               menu.appendToGroup(IWorkbenchActionConstants.MB_ADDITIONS, new Separator());
+               if (fPropertiesAction == null)
+                       fPropertiesAction = new MultiPropertyDialogAction(PlatformUI.getWorkbench().getActiveWorkbenchWindow(), getActionSite().getViewSite().getSelectionProvider());
+               if (!hasProperties(menu))
+                       menu.appendToGroup(IWorkbenchActionConstants.MB_ADDITIONS, fPropertiesAction);
+       }
+
+       private boolean hasProperties(IMenuManager menu) {
+               IContributionItem[] items = menu.getItems();
+               for (int i = 0; i < items.length; i++) {
+                       if (items[i] instanceof ActionContributionItem && ActionFactory.PROPERTIES.getCommandId().equals(((ActionContributionItem) items[i]).getAction().getActionDefinitionId()))
+                               return true;
+               }
+               return false;
+       }
+
+       public void fillActionBars(IActionBars actionBars) {
+               fOpenActionGroup.setContext(getContext());
+               fOpenActionGroup.fillActionBars(actionBars);
+       }
+
+}
diff --git a/org.tizen.common.externals/src/zipeditor/messages.properties b/org.tizen.common.externals/src/zipeditor/messages.properties
new file mode 100644 (file)
index 0000000..3227d2b
--- /dev/null
@@ -0,0 +1,62 @@
+ZipEditor.0=The file {0} has been changed on the file system, update the archive {1}? (Pressing No will revert the file to the original archive content)
+ZipEditor.1=File has been modified
+ZipEditor.10=\ (still opening...)
+ZipEditor.11=Refreshing Zip editor
+ZipEditor.12=An error has occurred while trying to save {0} 
+ZipEditor.13=Close
+ZipEditor.14=Save
+ZipEditor.2=Saving
+ZipEditor.3=Computing number of archive entries
+ZipEditor.4=File changed
+ZipEditor.5=The file has been changed on the file system. Do you want to reload the content of the editor?
+ZipEditor.6=File deleted
+ZipEditor.7=The file {0} has been deleted from the file system, what do you want to do?
+ZipEditor.8=Error
+ZipEditor.9={0} entries selected
+ZipEditorActionBarContributor.0=Delete all errors
+ZipEditorActionBarContributor.1=Select &Pattern...
+ZipEditorActionBarContributor.2=&Reverse Selection
+ZipEditorPlugin.0=See details
+ZipModel.0=Initializing zip model {0}
+AddOperation.0=Error while adding file
+AddOperation.1=Adding files to archive
+AddOperation.2=Adding
+AddOperation.3=Refresh zip viewer
+AddOperation.4=Computing number of files
+ExtractOperation.0=Extracting files
+ExtractOperation.1=Extracting
+ExtractOperation.2=Confirmation
+ExtractOperation.3=The file {0} does already exist. Should it be overridden?
+OpenFileOperation.0=Select workspace file
+OpenFileOperation.1=File is linked to multiple location
+ZipLabelProvider.0=Unknown
+ZipLabelProvider.1=Folder
+ZipLabelProvider.2={0}-File
+ZipNodeProperty.1=Name
+ZipNodeProperty.2=Type
+ZipNodeProperty.3=Date
+ZipNodeProperty.4=Size
+ZipNodeProperty.5=Ratio
+ZipNodeProperty.6=Packed size
+ZipNodeProperty.7=Crc
+ZipNodeProperty.8=Attributes
+ZipNodeProperty.9=Path
+ZipOutlinePage.0=Link with Editor
+ZipOutlinePage.1=Link with the active editor
+ZipOutlinePage.2=Sort
+ZipOutlinePage.3=Sort the elements
+ZipOutlinePage.4=Collapse All
+ZipOutlinePage.5=Collapse all elements
+ZipNodeProperty.10=Comment
+ZipNodeProperty.20=User ID
+ZipNodeProperty.21=User name
+ZipNodeProperty.22=Group ID
+ZipNodeProperty.23=Group name
+Utils.0=Extract and open file
+Utils.1=Extracting files
+NodePropertyPage.0=Irregular date ''{0}'', a correct sample is ''{1}''
+MultiElementPropertyPage.0=<unequal>
+MultiPreferenceDialog.0=Properties for {0}
+MultiPreferenceDialog.1=Properties for {0} elements
+TarNodePropertyPage.0=Invalid group id, must be an Integer
+TarNodePropertyPage.1=Invalid user id, must be an Integer
diff --git a/org.tizen.common.externals/src/zipeditor/model/Bzip2Node.java b/org.tizen.common.externals/src/zipeditor/model/Bzip2Node.java
new file mode 100644 (file)
index 0000000..2e0c1cf
--- /dev/null
@@ -0,0 +1,29 @@
+package zipeditor.model;\r
+\r
+import java.io.FileInputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+\r
+import org.apache.tools.bzip2.CBZip2InputStream;\r
+\r
+public class Bzip2Node extends Node {\r
+\r
+       public Bzip2Node(ZipModel model, String name, boolean isFolder) {\r
+               super(model, name, isFolder);\r
+       }\r
+\r
+       public Node create(ZipModel model, String name, boolean isFolder) {\r
+               return new Bzip2Node(model, name, isFolder);\r
+       }\r
+\r
+       protected InputStream doGetContent() throws IOException {\r
+               InputStream in = super.doGetContent();\r
+               if (in != null) {\r
+                       return in;\r
+               }\r
+               InputStream fileInput = new FileInputStream(model.getZipPath());\r
+               fileInput.skip(2);\r
+               return new CBZip2InputStream(fileInput);\r
+       }\r
+\r
+}\r
diff --git a/org.tizen.common.externals/src/zipeditor/model/FileAdapter.java b/org.tizen.common.externals/src/zipeditor/model/FileAdapter.java
new file mode 100644 (file)
index 0000000..6d39062
--- /dev/null
@@ -0,0 +1,50 @@
+package zipeditor.model;
+
+import java.io.File;
+
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.NullProgressMonitor;
+
+import zipeditor.Utils;
+import zipeditor.operations.ExtractOperation;
+
+public class FileAdapter implements IAdaptable {
+       private Node fNode;
+       private IFileStore fFileStore;
+       
+       public FileAdapter(Node node) {
+               if (node == null)
+                       throw new NullPointerException();
+               fNode = node;
+       }
+
+       public Object getAdapter(Class adapter) {
+               if (IFileStore.class.equals(adapter)) {
+                       if (fFileStore == null)
+                               fFileStore = extractNode();
+                       return fFileStore; 
+               } else if (Node.class.equals(adapter))
+                       return fNode;
+               return null;
+       }
+       
+       public boolean isAdapted() {
+               return fFileStore != null;
+       }
+       
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (!(obj instanceof FileAdapter))
+                       return false;
+               return fNode.equals(((FileAdapter) obj).fNode);
+       }
+
+       private IFileStore extractNode() {
+               ExtractOperation operation = new ExtractOperation();
+               File path = operation.extract(fNode, fNode.getModel().getTempDir(), true, new NullProgressMonitor());
+               return Utils.getFileStore(path);
+       }
+
+}
diff --git a/org.tizen.common.externals/src/zipeditor/model/GzipNode.java b/org.tizen.common.externals/src/zipeditor/model/GzipNode.java
new file mode 100644 (file)
index 0000000..a84a553
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.model;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.GZIPInputStream;
+
+public class GzipNode extends Node {
+       public GzipNode(ZipModel model, String name, boolean isFolder) {
+               super(model, name, isFolder);
+       }
+
+       public Node create(ZipModel model, String name, boolean isFolder) {
+               return new GzipNode(model, name, isFolder);
+       }
+
+       protected InputStream doGetContent() throws IOException {
+               InputStream in = super.doGetContent();
+               return in != null ? in : new GZIPInputStream(new FileInputStream(model.getZipPath()));
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/model/IModelListener.java b/org.tizen.common.externals/src/zipeditor/model/IModelListener.java
new file mode 100644 (file)
index 0000000..6d502f5
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.model;
+
+import java.util.EventListener;
+
+public interface IModelListener extends EventListener {
+       public class ModelChangeEvent {
+               private int fModelState;
+               private Node fModelRoot;
+               
+               public ModelChangeEvent(ZipModel model) {
+                       fModelState = model.getState();
+                       fModelRoot = model.getRoot();
+               }
+
+               public boolean isInitStarted() {
+                       return (fModelState & ZipModel.INIT_STARTED) > 0;
+               }
+               
+               public boolean isInitFinished() {
+                       return (fModelState & ZipModel.INIT_FINISHED) > 0;
+               }
+               
+               public boolean isInitializing() {
+                       return (fModelState & ZipModel.INITIALIZING) > 0;
+               }
+               
+               public Node getModelRoot() {
+                       return fModelRoot;
+               }
+       };
+
+       public void modelChanged(ModelChangeEvent event);
+}
diff --git a/org.tizen.common.externals/src/zipeditor/model/Node.java b/org.tizen.common.externals/src/zipeditor/model/Node.java
new file mode 100644 (file)
index 0000000..bf05c5d
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.model;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+public class Node extends PlatformObject {
+       protected Node parent;
+       protected List children;
+       protected int state;
+       protected String name;
+       protected long time;
+       protected long size;
+       protected File file;
+       private byte[] content;
+       protected ZipModel model;
+       
+       private String path;
+       private String fullPath;
+       
+       private Hashtable property;
+       
+       private final static int FOLDER = 0x01;
+       private final static int MODIFIED = 0x02;
+       private final static int ADDED = 0x04;
+
+       public Node(ZipModel model, String name, boolean isFolder) {
+               if (model == null)
+                       throw new NullPointerException();
+               if (name == null)
+                       throw new NullPointerException();
+               this.model = model;
+               this.name = name;
+               state |= isFolder ? FOLDER : 0;
+               this.time = System.currentTimeMillis();                 
+       }
+
+       public Node getParent() {
+               return parent;
+       }
+
+       public ZipModel getModel() {
+               return model;
+       }
+
+       public String getName() {
+               return name;
+       }
+
+       public void setName(String name) {
+               if (name == null)
+                       throw new NullPointerException();
+               if (name.equals(this.name))
+                       return;
+               this.name = name;
+               resetPathCache();
+               state |= MODIFIED;
+               model.setDirty(true);
+               model.notifyListeners();
+       }
+       
+       public String getPath() {
+               if (path == null) {
+                       if (parent == null) {
+                               path = new String();
+                       } else {
+                               StringBuffer sb = new StringBuffer(parent.getPath());
+                               if (isFolder()) {
+                                       sb.append(name);
+                                       sb.append('/');
+                               }
+                               path = sb.toString();
+                       }
+               }
+               return path;
+       }
+
+       public String getFullPath() {
+               if (fullPath == null) {
+                       StringBuffer sb = new StringBuffer(getPath());
+                       if (!isFolder())
+                               sb.append(name);
+                       fullPath = sb.toString();
+               }
+               return fullPath;
+       }
+
+       public String getType() {
+               int index = name.lastIndexOf('.');
+               return index != -1 ? name.substring(index + 1) : ""; //$NON-NLS-1$
+       }
+
+       public boolean isFolder() {
+               return (state & FOLDER) > 0;
+       }
+       
+       public boolean isModified() {
+               return (state & MODIFIED) > 0;
+       }
+
+       public boolean isAdded() {
+               return (state & ADDED) > 0;
+       }
+
+       public long getTime() {
+               return time;
+       }
+       
+       public void setTime(long time) {
+               if (time == this.time)
+                       return;
+               this.time = time;
+               state |= MODIFIED;
+               model.setDirty(true);
+               model.notifyListeners();
+       }
+
+       public long getSize() {
+               return size;
+       }
+
+       protected void setSize(long size) {
+               this.size = size;
+       }
+
+       public Node[] getChildren() {
+               return children != null ? (Node[]) children.toArray(new Node[children.size()]) : new Node[0];
+       }
+
+       public Node getChildByName(String name, boolean deep) {
+               if (children == null)
+                       return null;
+               for (int i = 0, n = children.size(); i < n; i++) {
+                       Node child = (Node) children.get(i);
+                       if (child.name.equals(name))
+                               return child;
+               }
+               if (!deep)
+                       return null;
+               for (int i = 0, n = children.size(); i < n; i++) {
+                       Node child = (Node) children.get(i);
+                       Node result = child.getChildByName(name, deep);
+                       if (result != null)
+                               return result;
+               }
+               return null;
+       }
+       
+       public Object getProperty(Object key) {
+               if (property == null)
+                       return null;
+               return property.get(key);
+       }
+       
+       public void setProperty(Object key, Object value) {
+               if (property == null)
+                       property = new Hashtable();
+               property.put(key, value);
+       }
+
+       public InputStream getContent() {
+               try {
+                       return doGetContent();
+               } catch (Exception e) {
+                       model.logError(e);
+                       return null;
+               }
+       }
+       
+       protected InputStream doGetContent() throws IOException {
+               if (file != null)
+                       return new FileInputStream(file);
+               if (content != null)
+                       return new ByteArrayInputStream(content);
+               return null;
+       }
+       
+       protected void setContent(byte[] buf) {
+               this.content = buf;
+       }
+       
+       private void internalAdd(Node node, int atIndex) {
+               node.parent = this;
+               if (children == null)
+                       children = new ArrayList();
+               if (atIndex < 0)
+                       atIndex = children.size();
+               children.add(atIndex, node);
+               model.setDirty(true);
+               model.notifyListeners();
+               node.resetPathCache();
+       }
+
+       public void add(Node node, Node beforeSibling) {
+               internalAdd(node, children != null && beforeSibling != null ? children.indexOf(beforeSibling) : -1);
+       }
+       
+       public void add(File file, Node beforeSibling, IProgressMonitor monitor) {
+               Node node = create(model, file.getName(), file.isDirectory());
+               add(node, beforeSibling);
+               node.state |= ADDED;
+               if (node.isFolder()) {
+                       node.time = file.lastModified();
+                       File[] files = file.listFiles();
+                       if (files != null) {
+                               for (int i = 0; i < files.length; i++) {
+                                       if (monitor.isCanceled())
+                                               break;
+                                       monitor.subTask(files[i].getName());
+                                       node.add(files[i], null, monitor);
+                               }
+                       }
+                       node.state |= MODIFIED;
+               } else {
+                       node.updateContent(file);
+                       monitor.worked(1);
+               }
+       }
+       
+       public void updateContent(File file) {
+               this.file = file;
+               time = file.lastModified();
+               size = file.length();
+               state |= MODIFIED;
+               model.setDirty(true);
+               model.notifyListeners();
+       }
+       
+       /**
+        * @param entry the entry that updates the node 
+        */
+       public void update(Object entry) {
+               // does nothing not knowing the type of entry
+       }
+
+       public void remove(Node node) {
+               if (children == null)
+                       return;
+               children.remove(node);
+               model.setDirty(true);
+               model.notifyListeners();
+               node.clear();
+       }
+       
+       private void clear() {
+               if (children != null) {
+                       for (Iterator it = children.iterator(); it.hasNext();) {
+                               ((Node) it.next()).clear();
+                               it.remove();
+                       }
+                       children = null;
+               }
+       }
+       
+       public void reset() {
+               model.deleteFile(file);
+               file = null;
+               state &= -1 ^ MODIFIED;
+               model.notifyListeners();
+       }
+
+       private void resetPathCache() {
+               path = fullPath = null;
+               if (children != null) {
+                       for (int i = 0; i < children.size(); i++)
+                               ((Node) children.get(i)).resetPathCache();
+               }
+       }
+
+       public Node create(ZipModel model, String name, boolean isFolder) {
+               return new Node(model, name, isFolder);
+       }
+
+       public String toString() {
+               return getFullPath();
+       }
+
+       public Object getAdapter(Class adapter) {
+               if (Node.class == adapter)
+                       return this;
+               if (IWorkbenchAdapter.class == adapter)
+                       return new NodeWorkbenchAdapter(this);
+               return super.getAdapter(adapter);
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/model/NodeProperty.java b/org.tizen.common.externals/src/zipeditor/model/NodeProperty.java
new file mode 100644 (file)
index 0000000..d6f7519
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.model;
+
+import zipeditor.Messages;
+
+public class NodeProperty {
+
+       public static final int NAME = 1;
+       public static final int TYPE = 2;
+       public static final int DATE = 3;
+       public static final int SIZE = 4;
+       public static final int PATH = 9;
+       public static final NodeProperty PNAME = new NodeProperty(NAME);
+       public static final NodeProperty PTYPE = new NodeProperty(TYPE);
+       public static final NodeProperty PDATE = new NodeProperty(DATE);
+       public static final NodeProperty PSIZE = new NodeProperty(SIZE);
+       public static final NodeProperty PPATH = new NodeProperty(PATH);
+       protected int type;
+
+       protected NodeProperty(int type) {
+               this.type = type;
+       }
+
+       public int getType() {
+               return type;
+       }
+
+       public String toString() {
+               return Messages.getString("ZipNodeProperty." + type); //$NON-NLS-1$
+       }
+
+}
\ No newline at end of file
diff --git a/org.tizen.common.externals/src/zipeditor/model/NodeWorkbenchAdapter.java b/org.tizen.common.externals/src/zipeditor/model/NodeWorkbenchAdapter.java
new file mode 100644 (file)
index 0000000..14379b9
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.model;
+
+import org.eclipse.ui.model.WorkbenchAdapter;
+
+public class NodeWorkbenchAdapter extends WorkbenchAdapter {
+       private Node node;
+
+       public NodeWorkbenchAdapter(Node node) {
+               this.node = node;
+       }
+       
+       public String getLabel(Object object) {
+               return node.getName();
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/model/TarNode.java b/org.tizen.common.externals/src/zipeditor/model/TarNode.java
new file mode 100644 (file)
index 0000000..f4aeb93
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.model;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.GZIPInputStream;
+
+import org.apache.tools.bzip2.CBZip2InputStream;
+import org.apache.tools.tar.TarEntry;
+import org.apache.tools.tar.TarInputStream;
+
+public class TarNode extends Node {
+       private class EntryStream extends InputStream {
+               private InputStream in;
+               private EntryStream(TarEntry entry, TarInputStream in) throws IOException {
+                       for (TarEntry e = null; (e = in.getNextEntry()) != null; ) {
+                               if (!entry.equals(e))
+                                       continue;
+                               if (entry.getSize() < 10000000) {
+                                       ByteArrayOutputStream out = new ByteArrayOutputStream();
+                                       in.copyEntryContents(out);
+                                       this.in = new ByteArrayInputStream(out.toByteArray());
+                               } else {
+                                       File tmpFile = new File(model.getTempDir(), Integer.toString((int) System.currentTimeMillis()));
+                                       FileOutputStream out = new FileOutputStream(tmpFile);
+                                       in.copyEntryContents(out);
+                                       out.close();
+                                       this.in = new FileInputStream(tmpFile);
+                               }
+                               break;
+                       }
+                       in.close();
+               }
+               public int read() throws IOException {
+                       return in != null ? in.read() : -1;
+               }
+               public void close() throws IOException {
+                       if (in != null)
+                               in.close();
+               }
+       };
+
+       private TarEntry tarEntry;
+       private int groupId;
+       private String groupName = new String();
+       private int userId;
+       private String userName = new String();
+       private int mode;
+
+       public TarNode(ZipModel model, TarEntry entry, String name, boolean isFolder) {
+               this(model, name, isFolder);
+               tarEntry = entry;
+               if (tarEntry != null) {
+                       size = tarEntry.getSize();
+                       if (tarEntry.getModTime() != null)
+                               time = tarEntry.getModTime().getTime();
+                       groupId = tarEntry.getGroupId();
+                       groupName = tarEntry.getGroupName();
+                       userId = tarEntry.getUserId();
+                       userName = tarEntry.getUserName();
+                       mode = tarEntry.getMode();
+               }
+       }
+
+       public TarNode(ZipModel model, String name, boolean isFolder) {
+               super(model, name, isFolder);
+       }
+
+    public int getGroupId() {
+        return groupId;
+    }
+
+    public String getGroupName() {
+        return groupName;
+    }
+
+    public int getUserId() {
+        return userId;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public int getMode() {
+        return mode;
+    }
+    
+    public void setGroupId(int groupId) {
+       if (groupId == this.groupId)
+               return;
+               this.groupId = groupId;
+               model.setDirty(true);
+               model.notifyListeners();
+       }
+    
+    public void setGroupName(String groupName) {
+       if (groupName == this.groupName || groupName != null && groupName.equals(this.groupName))
+               return;
+               this.groupName = groupName;
+               model.setDirty(true);
+               model.notifyListeners();
+       }
+    
+    public void setUserId(int userId) {
+       if (userId == this.userId)
+               return;
+               this.userId = userId;
+               model.setDirty(true);
+               model.notifyListeners();
+       }
+    
+    public void setUserName(String userName) {
+       if (userName == this.userName || userName != null && userName.equals(this.userName))
+               return;
+               this.userName = userName;
+               model.setDirty(true);
+               model.notifyListeners();
+       }
+
+    protected InputStream doGetContent() throws IOException {
+               InputStream in = super.doGetContent();
+               if (in != null)
+                       return in;
+               if (tarEntry != null)
+                       return new EntryStream(tarEntry, getTarFile());
+               return null;
+       }
+       
+       private TarInputStream getTarFile() throws IOException {
+               switch (model.getType()) {
+               default:
+               case ZipModel.TAR:
+                       return new TarInputStream(new FileInputStream(model.getZipPath()));
+               case ZipModel.TARGZ:
+                       return new TarInputStream(new GZIPInputStream(new FileInputStream(model.getZipPath())));
+               case ZipModel.TARBZ2:
+                               InputStream in = new FileInputStream(model.getZipPath());
+                               in.skip(2);
+                               return new TarInputStream(new CBZip2InputStream(in));
+               }
+       }
+       
+       public void reset() {
+               super.reset();
+               size = tarEntry.getSize();
+               if (tarEntry.getModTime() != null)
+                       time = tarEntry.getModTime().getTime();
+       }
+       
+       public void update(Object entry) {
+               if (!(entry instanceof TarEntry))
+                       return;
+               TarEntry tarEntry = (TarEntry) entry;
+               time = tarEntry.getModTime().getTime();
+       }
+
+       public Node create(ZipModel model, String name, boolean isFolder) {
+               return new TarNode(model, name, isFolder);
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/model/TarNodeProperty.java b/org.tizen.common.externals/src/zipeditor/model/TarNodeProperty.java
new file mode 100644 (file)
index 0000000..dfbc90b
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.model;
+
+public class TarNodeProperty extends NodeProperty {
+
+       public final static int USER_ID = 20;
+       public final static int USER_NAME = 21;
+       public final static int GROUP_ID = 22;
+       public final static int GROUP_NAME = 23;
+       
+       public final static TarNodeProperty PUSER_ID = new TarNodeProperty(USER_ID);
+       public final static TarNodeProperty PUSER_NAME = new TarNodeProperty(USER_NAME);
+       public final static TarNodeProperty PGROUP_ID = new TarNodeProperty(GROUP_ID);
+       public final static TarNodeProperty PGROUP_NAME = new TarNodeProperty(GROUP_NAME);
+
+       private TarNodeProperty(int type) {
+               super(type);
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/model/ZipContentDescriber.java b/org.tizen.common.externals/src/zipeditor/model/ZipContentDescriber.java
new file mode 100644 (file)
index 0000000..41e97ee
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.model;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.content.IContentDescriber;
+import org.eclipse.core.runtime.content.IContentDescription;
+
+import zipeditor.ZipEditorPlugin;
+
+public class ZipContentDescriber implements IContentDescriber {
+       private final static Set ALL_TYPES = new HashSet();
+
+       public final static String ZIP_FILE = add("zipfile"); //$NON-NLS-1$
+       public final static String GZ_FILE = add("gzipfile"); //$NON-NLS-1$
+       public final static String TAR_FILE = add("tarfile"); //$NON-NLS-1$
+       public final static String TGZ_FILE = add("targzfile"); //$NON-NLS-1$
+       public final static String BZ2_FILE = add("bz2file"); //$NON-NLS-1$
+       public final static String TBZ_FILE = add("tarbz2file"); //$NON-NLS-1$
+
+       private final static String EMPTY = "empty"; //$NON-NLS-1$
+
+       private static String add(String s) {
+               String contentTypeId = ZipEditorPlugin.PLUGIN_ID + '.' + s;
+               ALL_TYPES.add(contentTypeId);
+               return contentTypeId;
+       }
+
+       public static boolean isForUs(String contentTypeId) {
+               return ALL_TYPES.contains(contentTypeId);
+       }
+
+       public int describe(InputStream contents, IContentDescription description)
+                       throws IOException {
+
+               String type = detectType(contents);
+               if (type == null)
+                       return INVALID;
+               if (description == null || type == EMPTY)
+                       return VALID;
+
+               String contentTypeId = description.getContentType() != null ? description.getContentType().getId() : null;
+               if (type.equals(contentTypeId))
+                       return VALID;
+               if (type == TGZ_FILE && GZ_FILE.equals(contentTypeId))
+                       return VALID;
+               if (type == TBZ_FILE && BZ2_FILE.equals(contentTypeId))
+                       return VALID;
+
+               return INVALID;
+       }
+
+       private String detectType(InputStream contents) {
+               switch (ZipModel.detectType(contents)) {
+               default:
+                       return null;
+               case ZipModel.ZIP:
+                       return ZIP_FILE;
+               case ZipModel.TAR:
+                       return TAR_FILE;
+               case ZipModel.GZ:
+                       return GZ_FILE;
+               case ZipModel.TARGZ:
+                       return TGZ_FILE;
+               case ZipModel.BZ2:
+                       return BZ2_FILE;
+               case ZipModel.TARBZ2:
+                       return TBZ_FILE;
+               case ZipModel.EMPTY:
+                       return EMPTY; 
+               }
+       }
+
+       public QualifiedName[] getSupportedOptions() {
+               return IContentDescription.ALL;
+       }
+
+}
diff --git a/org.tizen.common.externals/src/zipeditor/model/ZipModel.java b/org.tizen.common.externals/src/zipeditor/model/ZipModel.java
new file mode 100644 (file)
index 0000000..ab2ac7d
--- /dev/null
@@ -0,0 +1,579 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.model;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.tools.bzip2.CBZip2InputStream;
+import org.apache.tools.bzip2.CBZip2OutputStream;
+import org.apache.tools.tar.TarConstants;
+import org.apache.tools.tar.TarEntry;
+import org.apache.tools.tar.TarInputStream;
+import org.apache.tools.tar.TarOutputStream;
+import org.apache.tools.tar.TarUtils;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.ListenerList;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+
+import zipeditor.Messages;
+import zipeditor.PreferenceConstants;
+import zipeditor.Utils;
+import zipeditor.ZipEditorPlugin;
+import zipeditor.model.IModelListener.ModelChangeEvent;
+
+public class ZipModel {
+       public interface IErrorReporter {
+               void reportError(IStatus message);
+       }
+
+       public final static int ZIP = 1;
+       public final static int TAR = 2;
+       public final static int GZ = 3;
+       public final static int TARGZ = 4;
+       public final static int BZ2 = 5;
+       public final static int TARBZ2 = 6;
+       public final static int EMPTY = 99;
+
+       public final static int INIT_STARTED = 0x01;
+       public final static int INIT_FINISHED = 0x02;
+       public final static int INITIALIZING = 0x04;
+       public final static int DIRTY = 0x08;
+
+       /** @see: {@link org.apache.tools.tar.TarEntry#parseTarHeader(byte[])} */
+       private static final int TAR_MAGIC_OFFSET = TarConstants.NAMELEN //
+                       + TarConstants.MODELEN //
+                       + TarConstants.UIDLEN //
+                       + TarConstants.GIDLEN //
+                       + TarConstants.SIZELEN //
+                       + TarConstants.MODTIMELEN //
+                       + TarConstants.CHKSUMLEN //
+                       + 1 // linkFlag
+                       + TarConstants.NAMELEN; // linkName
+
+       public static int typeFromName(String string) {
+               if (string != null) {
+                       String lowerCase = string.toLowerCase();
+                       if (lowerCase.endsWith(".tgz") || lowerCase.endsWith(".tar.gz")) //$NON-NLS-1$ //$NON-NLS-2$
+                               return TARGZ;
+                       if (lowerCase.endsWith(".gz")) //$NON-NLS-1$
+                               return GZ;
+                       if (lowerCase.endsWith(".tar")) //$NON-NLS-1$
+                               return TAR;
+                       if (lowerCase.endsWith(".tbz") || lowerCase.endsWith(".tar.bz2")) //$NON-NLS-1$ //$NON-NLS-2$
+                               return TARBZ2;
+                       if (lowerCase.endsWith(".bz2")) //$NON-NLS-1$
+                               return BZ2;
+               }
+               return ZIP;
+       }
+
+       public static int detectType(InputStream contents) {
+               if (!contents.markSupported())
+                       contents = new BufferedInputStream(contents);
+               try {
+                       contents.mark(1000000); // an entry which exceeds this limit cannot be detected
+                       int count = contents.read();
+                       contents.reset();
+                       if (count == -1)
+                               return EMPTY;
+                       ZipInputStream zip = new ZipInputStream(contents);
+                       if (zip.getNextEntry() != null) {
+                               contents.reset();
+                               return ZIP;
+                       }
+                       contents.reset();
+                       try {
+                               contents.skip(2);
+                               CBZip2InputStream bzip = new CBZip2InputStream(contents);
+                               if (isTarArchive(bzip)) {
+                                       contents.reset();
+                                       return TARBZ2;
+                               } else {
+                                       contents.reset();
+                                       return BZ2;
+                               }
+                       } catch (IOException ioe) {
+                               // thrown in constructor, no bzip2
+                       }
+                       contents.reset();
+                       try {
+                               GZIPInputStream gzip = new GZIPInputStream(contents);
+                               if (isTarArchive(gzip)) {
+                                       contents.reset();
+                                       return TARGZ;
+                               } else {
+                                       contents.reset();
+                                       return GZ;
+                               }
+                       } catch (IOException ioe) {
+                               // thrown in constructor, no gzip
+                       }
+                       contents.reset();
+                       
+                       // Es gibt gueltige Tar-Archive ohne TAR-Header, die von
+                       // isTarArchive nicht erkannt werden, magic ist dann leer, deshalb
+                       // bleibt TAR hier default
+                       //
+                       return TAR;
+
+               } catch (IOException e) {
+                       throw new IllegalStateException(e);
+               }
+       }
+
+       private static boolean isTarArchive(InputStream bzip) throws IOException {
+               byte[] tarEntryHeader = new byte[TAR_MAGIC_OFFSET + TarConstants.MAGICLEN];
+               bzip.read(tarEntryHeader);
+               String magic = String.valueOf(TarUtils.parseName(tarEntryHeader, TAR_MAGIC_OFFSET, TarConstants.MAGICLEN));
+               return TarConstants.TMAGIC.equals(magic) || TarConstants.GNU_TMAGIC.equals(magic);
+       }
+
+       private Node root;
+       private File zipPath;
+       private int state;
+       private int type;
+       private File tempDir;
+       private boolean readonly;
+       private Boolean storeFolders;
+       private ListenerList listenerList = new ListenerList();
+       private IErrorReporter errorReporter;
+       
+       public ZipModel(File path, final InputStream inputStream, boolean readonly) {
+               this(path, inputStream, readonly, null);
+       }
+
+       public ZipModel(File path, final InputStream inputStream, boolean readonly, IErrorReporter errorReporter) {
+               zipPath = path;
+               this.readonly = readonly;
+               this.errorReporter = errorReporter;
+               state |= INITIALIZING;
+               if (path != null && path.length() >= 10000000) {
+                       Thread initThread = new Thread(Messages.getFormattedString("ZipModel.0", path.getName())) { //$NON-NLS-1$
+                               public void run() {
+                                       initialize(inputStream);
+                               }
+                       };
+                       initThread.start();
+               } else {
+                       initialize(inputStream);
+               }
+       }
+       
+       public void logError(Object message) {
+               IStatus status = ZipEditorPlugin.log(message);
+               if (errorReporter != null)
+                       errorReporter.reportError(status);
+       }
+
+       private void initialize(InputStream inputStream) {
+               long time = System.currentTimeMillis();
+               InputStream zipStream = inputStream;
+               try {
+                       zipStream = detectStream(inputStream);
+                       root = getRoot(zipStream);
+                       readStream(zipStream);
+               } catch (IOException e) {
+                       // ignore
+               } finally {
+                       if (zipStream != null) {
+                               try {
+                                       zipStream.close();
+                               } catch (IOException e) {
+                                       logError(e);
+                               }
+                       }
+                       state &= -1 ^ INITIALIZING;
+                       state |= INIT_FINISHED;
+                       notifyListeners();
+                       state &= -1 ^ INIT_FINISHED;
+                       if (ZipEditorPlugin.DEBUG)
+                               System.out.println(zipPath + " initialized in " + (System.currentTimeMillis() - time) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
+               }
+       }
+
+       private Node getRoot(InputStream zipStream) throws IOException {
+               if (zipStream instanceof ZipInputStream) {
+                       return new ZipNode(this, "", true); //$NON-NLS-1$
+               }
+               if (zipStream instanceof TarInputStream) {
+                       return new TarNode(this, "", true); //$NON-NLS-1$
+               }
+               if (zipStream instanceof CBZip2InputStream) {
+                       return new Bzip2Node(this, "", true); //$NON-NLS-1$
+               }
+               return new GzipNode(this, "", true); //$NON-NLS-1$
+       }
+
+       private void readStream(InputStream zipStream) {
+               ZipEntry zipEntry = null;
+               TarEntry tarEntry = null;
+               state |= INIT_STARTED;
+               boolean isNoEntry = zipStream instanceof GZIPInputStream || zipStream instanceof CBZip2InputStream;
+               while (true) {
+                       if (!isInitializing()) {
+                               state |= DIRTY;
+                               break;
+                       }
+                       try {
+                               if (zipStream instanceof ZipInputStream)
+                                       zipEntry = ((ZipInputStream) zipStream).getNextEntry();
+                               else if (zipStream instanceof TarInputStream)
+                                       tarEntry = ((TarInputStream) zipStream).getNextEntry();
+                       } catch (Exception e) {
+                               logError(e);
+                               break;
+                       }
+                       if ((!isNoEntry && zipEntry == null && tarEntry == null) || (isNoEntry && root.children != null)) {
+                               state &= -1 ^ DIRTY;
+                               break;
+                       }
+                       String entryName = zipEntry != null ? zipEntry.getName() : tarEntry != null ? tarEntry.getName() : zipPath
+                                       .getName().endsWith(".gz") ? zipPath.getName().substring(0, //$NON-NLS-1$
+                                       zipPath.getName().length() - 3)
+                                       : zipPath.getName().endsWith(".bz2") ? zipPath.getName().substring(0, //$NON-NLS-1$
+                                                       zipPath.getName().length() - 4) : zipPath.getName();
+                       String[] names = splitName(entryName);
+                       Node node = null;
+                       int n = names.length - 1;
+                       for (int i = 0; i < n; i++) {
+                               String pathSeg = names[i];
+                               Node parent = node != null ? node : root;
+                               node = parent.getChildByName(pathSeg, false);
+                               if (node == null) {
+                                       parent.add(node = parent.create(this, pathSeg, true), null);
+                                       node.time = -1;
+                               }
+                       }
+                       boolean isFolder = entryName.endsWith("/") || entryName.endsWith("\\") || //$NON-NLS-1$ //$NON-NLS-2$
+                                       (zipEntry != null && zipEntry.isDirectory() || tarEntry != null && tarEntry.isDirectory());
+                       if (isFolder && storeFolders == null)
+                               storeFolders = Boolean.TRUE;
+                       if (node == null)
+                               node = root;
+                       Node existingNode = n == -1 ? null : node.getChildByName(names[n], false);
+                       if (existingNode != null) {
+                               existingNode.update(zipEntry != null ? (Object) zipEntry : tarEntry);
+                       } else {
+                               String name = n >= 0 ? names[n] : "/"; //$NON-NLS-1$
+                               Node newChild = zipEntry != null ? new ZipNode(this, zipEntry, name, isFolder)
+                                               : tarEntry != null ? (Node) new TarNode(this, tarEntry, name, isFolder)
+                                                               : zipStream instanceof CBZip2InputStream ? (Node) new Bzip2Node(
+                                                                               this, name, isFolder) : new GzipNode(this, name, isFolder);
+                               node.add(newChild, null);
+                               long entrySize = 0;
+                               if (zipPath == null || isNoEntry) {
+                                       byte[] buf = new byte[8000];
+                                       ByteArrayOutputStream out = null;
+                                       try {
+                                               for (int count = 0; (count = zipStream.read(buf)) != -1; ) {
+                                                       if (out == null)
+                                                               out = new ByteArrayOutputStream();
+                                                       out.write(buf, 0, count);
+                                                       if (isNoEntry)
+                                                               entrySize += count;
+                                               }
+                                       } catch (Exception e) {
+                                               logError(e);
+                                       }
+                                       if (out != null)
+                                               newChild.setContent(out.toByteArray());
+                               }
+                               if (zipStream instanceof ZipInputStream) {
+                                       try {
+                                               ((ZipInputStream) zipStream).closeEntry();
+                                       } catch (Exception e) {
+                                               logError(e);
+                                       }
+                               }
+                               newChild.setSize(zipEntry != null ? zipEntry.getSize()
+                                               : tarEntry != null ? tarEntry.getSize() : entrySize);
+                       }
+                       state &= -1 ^ INIT_STARTED;
+               }
+       }
+
+       private InputStream detectStream(InputStream contents) throws IOException {
+               BufferedInputStream in = new BufferedInputStream(contents);
+               switch (type = detectType(in)) {
+               default:
+                       return in;
+               case ZIP:
+                       return new ZipInputStream(in);
+               case TAR:
+                       return new TarInputStream(in);
+               case GZ:
+                       return new GZIPInputStream(in);
+               case TARGZ:
+                       return new TarInputStream(new GZIPInputStream(in));
+               case BZ2:
+                       in.skip(2);
+                       return new CBZip2InputStream(in);
+               case TARBZ2:
+                       in.skip(2);
+                       return new TarInputStream(new CBZip2InputStream(in));
+               }
+       }
+
+       public InputStream save(int type, IProgressMonitor monitor) throws IOException {
+               File tmpFile = new File(root.getModel().getTempDir(), Integer.toString((int) System.currentTimeMillis()));
+               OutputStream out = new FileOutputStream(tmpFile);
+               try {
+                       switch (type) {
+                       case GZ:
+                               out = new GZIPOutputStream(out);
+                               break;
+                       case TAR:
+                               out = new TarOutputStream(out);
+                               break;
+                       case TARGZ:
+                               out = new TarOutputStream(new GZIPOutputStream(out));
+                               break;
+                       case ZIP:
+                               out = new ZipOutputStream(out);
+                               break;
+                       case TARBZ2:
+                               out.write(new byte[] { 'B', 'Z' });
+                               out = new TarOutputStream(new CBZip2OutputStream(out));
+                               break;
+                       case BZ2:
+                               out.write(new byte[] { 'B', 'Z' });
+                               out = new CBZip2OutputStream(out);
+                               break;
+                       }
+                       if (out instanceof TarOutputStream)
+                               ((TarOutputStream) out).setLongFileMode(TarOutputStream.LONGFILE_GNU);
+                       saveNodes(out, root, type, isStoreFolders(), monitor);
+               } catch (Exception e) {
+                       logError(e);
+               } finally {
+                       out.close();
+               }
+               return new FileInputStream(tmpFile);
+       }
+
+       private void saveNodes(OutputStream out, Node node, int type, boolean storeFolders, IProgressMonitor monitor) throws IOException {
+               if (out == null)
+                       return;
+               Node[] children = node.getChildren();
+               for (int i = 0; i < children.length; i++) {
+                       if (monitor.isCanceled())
+                               break;
+                       Node child = children[i];
+                       String entryName = child.getPath() + child.getName();
+                       if (child.isFolder()) {
+                               saveNodes(out, child, type, storeFolders, monitor);
+                               if (!storeFolders)
+                                       continue;
+                               entryName = child.getPath();
+                       }
+                       ZipEntry zipEntry = type == ZIP ? new ZipEntry(entryName) : null;
+                       TarEntry tarEntry = type == TAR || type == TARGZ || type == TARBZ2 ? new TarEntry(entryName) : null;
+                       if (zipEntry != null) {
+                               zipEntry.setTime(child.getTime());
+                               if (child instanceof ZipNode)
+                                       zipEntry.setComment(((ZipNode) child).getComment());
+                       } else if (tarEntry != null) {
+                               tarEntry.setModTime(child.getTime());
+                               tarEntry.setSize(child.getSize());
+                               if (child instanceof TarNode) {
+                                       TarNode tarNode = (TarNode) child;
+                                       tarEntry.setGroupId(tarNode.getGroupId());
+                                       tarEntry.setGroupName(tarNode.getGroupName());
+                                       tarEntry.setUserId(tarNode.getUserId());
+                                       tarEntry.setUserName(tarNode.getUserName());
+                                       tarEntry.setGroupId(tarNode.getGroupId());
+                                       tarEntry.setMode(tarNode.getMode());
+                               } else {
+                                       tarEntry.setMode(TarEntry.DEFAULT_FILE_MODE);
+                               }
+                       }
+                       
+                       if (out instanceof ZipOutputStream)
+                               ((ZipOutputStream) out).putNextEntry(zipEntry);
+                       else if (out instanceof TarOutputStream)
+                               ((TarOutputStream) out).putNextEntry(tarEntry);
+                       Utils.readAndWrite(child.getContent(), out, false);
+                       if (tarEntry != null)
+                               ((TarOutputStream) out).closeEntry();
+                       monitor.worked(1);
+               }
+       }
+
+       public Node createFolderNode(Node parent, String name) {
+               Node newNode = null;
+               String[] names = splitName(name);
+               for (int i = 0; i < names.length; i++) {
+                       newNode = parent.getChildByName(names[i], false);
+                       if (newNode == null) {
+                               newNode = parent.create(this, names[i], true);
+                               parent.add(newNode, null);
+                       }
+                       parent = newNode;
+               }
+               return newNode;
+       }
+
+       private String[] splitName(String name) {
+               List list = new ArrayList();
+               while (name != null && name.length() > 0) {
+                       int index = name.indexOf('/');
+                       if (index == -1)
+                               index = name.indexOf('\\');
+                       if (index != -1) {
+                               list.add(name.substring(0, index));
+                               name = name.substring(index + 1);
+                       } else {
+                               list.add(name);
+                               name = new String();
+                       }
+               }
+               return (String[]) list.toArray(new String[list.size()]);
+       }
+       
+       public void addModelListener(IModelListener listener) {
+               listenerList.add(listener);
+       }
+       
+       public void removeModelListener(IModelListener listener) {
+               listenerList.remove(listener);
+       }
+       
+       protected void notifyListeners() {
+               Object[] listeners = listenerList.getListeners();
+               ModelChangeEvent event = new ModelChangeEvent(this);
+               for (int i = 0; i < listeners.length; i++) {
+                       ((IModelListener) listeners[i]).modelChanged(event);
+               }
+       }
+
+       public void dispose() {
+               state &= -1 ^ INITIALIZING;
+               deleteTempDir(tempDir);
+               tempDir = null;
+               ZipEditorPlugin.getDefault().removeFileMonitors(this);
+               if (ZipEditorPlugin.DEBUG)
+                       System.out.println(zipPath + " disposed"); //$NON-NLS-1$
+       }
+       
+       private void deleteTempDir(final File tmpDir) {
+               if (deleteFile(tmpDir))
+                       return;
+               Job job = new Job("Deleting temporary directory") { //$NON-NLS-1$
+                       protected IStatus run(IProgressMonitor monitor) {
+                               monitor.beginTask("Waiting for accessing tasks to be finished", IProgressMonitor.UNKNOWN); //$NON-NLS-1$
+                               do {
+                                       try {
+                                               Thread.sleep(2000);
+                                       } catch (InterruptedException e) {
+                                       }
+                                       if (monitor.isCanceled())
+                                               break;
+                               } while (!deleteFile(tmpDir));
+                               monitor.done();
+                               return Status.OK_STATUS;
+                       }
+               };
+               job.setRule(ResourcesPlugin.getWorkspace().getRoot());
+               job.schedule();
+       }
+
+       boolean deleteFile(File file) {
+               if (file == null)
+                       return true;
+               if (file.isDirectory()) {
+                       File[] files = file.listFiles();
+                       if (files != null) {
+                               for (int i = 0; i < files.length; i++) {
+                                       deleteFile(files[i]);
+                               }
+                       }
+               }
+               boolean success = file.delete();
+               if (!success)
+                       System.out.println("Couldn't delete " + file); //$NON-NLS-1$
+               return success;
+       }
+
+       public File getTempDir() {
+               if (tempDir == null) {
+                       File sysTmpDir = new File(System.getProperty("java.io.tmpdir")); //$NON-NLS-1$
+                       tempDir = new File(sysTmpDir, "zip" + (int) System.currentTimeMillis()); //$NON-NLS-1$
+                       tempDir.mkdirs();
+               }
+               return tempDir;
+       }
+
+       public Node getRoot() {
+               return root;
+       }
+       
+       public int getType() {
+               return type;
+       }
+       
+       int getState() {
+               return state;
+       }
+
+       public boolean isInitializing() {
+               return (state & INITIALIZING) > 0;
+       }
+
+       public boolean isDirty() {
+               return (state & DIRTY) > 0;
+       }
+       
+       public void setDirty(boolean dirty) {
+               if (dirty) {
+                       if (!isInitializing())
+                               state |= DIRTY;
+               } else {
+                       state &= -1 ^ DIRTY;
+               }
+       }
+       
+       public boolean isReadonly() {
+               return readonly;
+       }
+
+       public File getZipPath() {
+               return zipPath;
+       }
+       
+       public Node findNode(String path) {
+               String[] names = splitName(path);
+               Node node = root;
+               for (int i = 0; i < names.length && node != null; i++) {
+                       node = node.getChildByName(names[i], false);
+               }
+               return node;
+       }
+
+       public boolean isStoreFolders() {
+               return storeFolders != null ? storeFolders.booleanValue() : ZipEditorPlugin.getDefault()
+                               .getPreferenceStore().getBoolean(PreferenceConstants.STORE_FOLDERS_IN_ARCHIVES);
+       }
+
+       public void setStoreFolders(boolean store) {
+               storeFolders = store ? Boolean.TRUE : Boolean.FALSE;
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/model/ZipNode.java b/org.tizen.common.externals/src/zipeditor/model/ZipNode.java
new file mode 100644 (file)
index 0000000..5ff8f2b
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.model;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+public class ZipNode extends Node {
+       private class EntryStream extends InputStream {
+               private InputStream in;
+               private ZipFile zipFile;
+               private EntryStream(ZipEntry entry, ZipFile zipFile) throws IOException {
+                       in = zipFile.getInputStream(entry);
+                       this.zipFile = zipFile;
+               }
+               public int read() throws IOException {
+                       return in.read();
+               }
+               public void close() throws IOException {
+                       in.close();
+                       if (zipFile != null)
+                               zipFile.close();
+               }
+       };
+
+       private String comment;
+       private ZipEntry zipEntry;
+
+       public ZipNode(ZipModel model, ZipEntry entry, String name, boolean isFolder) {
+               this(model, name, isFolder);
+               zipEntry = entry;
+               if (entry != null) {
+                       time = entry.getTime();
+                       size = entry.getSize();
+                       comment = entry.getComment();
+               }
+       }
+       
+       public ZipNode(ZipModel model, String name, boolean isFolder) {
+               super(model, name, isFolder);
+       }
+       
+       public String getComment() {
+               return comment;
+       }
+       
+       public void setComment(String comment) {
+               if (comment == this.comment || comment != null && comment.equals(this.comment))
+                       return;
+               this.comment = comment;
+               model.setDirty(true);
+               model.notifyListeners();
+       }
+       
+       public byte[] getExtra() {
+               return zipEntry != null && file == null && zipEntry.getExtra() != null ? zipEntry.getExtra() : new byte[0];
+       }
+       
+       public long getCrc() {
+               return zipEntry != null && file == null ? zipEntry.getCrc() : 0;
+       }
+       
+       public long getCompressedSize() {
+               return zipEntry != null && file == null ? zipEntry.getCompressedSize() : 0;
+       }
+       
+       public double getRatio() {
+               return zipEntry != null && file == null ? (zipEntry.getSize() - zipEntry.getCompressedSize()) / (double) zipEntry.getSize() * 100 : 0;
+       }
+
+       protected InputStream doGetContent() throws IOException {
+               InputStream in = super.doGetContent();
+               if (in != null)
+                       return in;
+               if (zipEntry != null)
+                       return new EntryStream(zipEntry, model.getZipPath() != null ?
+                                       new ZipFile(model.getZipPath()) : null);
+               return null;
+       }
+       
+       public void reset() {
+               super.reset();
+               if (zipEntry != null) {
+                       time = zipEntry.getTime();
+                       size = zipEntry.getSize();
+               }
+       }
+       
+       public void update(Object entry) {
+               if (!(entry instanceof ZipEntry))
+                       return;
+               ZipEntry zipEntry = (ZipEntry) entry;
+               time = zipEntry.getTime();
+       }
+       
+       public Node create(ZipModel model, String name, boolean isFolder) {
+               return new ZipNode(model, name, isFolder);
+       }
+       
+}
diff --git a/org.tizen.common.externals/src/zipeditor/model/ZipNodeProperty.java b/org.tizen.common.externals/src/zipeditor/model/ZipNodeProperty.java
new file mode 100644 (file)
index 0000000..a3fa903
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.model;
+
+public class ZipNodeProperty extends NodeProperty {
+       
+       public final static int RATIO = 5;
+       public final static int PACKED_SIZE = 6;
+       public final static int CRC = 7;
+       public final static int ATTR = 8;
+       public final static int COMMENT = 10;
+       
+       public final static ZipNodeProperty PRATIO = new ZipNodeProperty(RATIO);
+       public final static ZipNodeProperty PPACKED_SIZE = new ZipNodeProperty(PACKED_SIZE);
+       public final static ZipNodeProperty PCRC = new ZipNodeProperty(CRC);
+       public final static ZipNodeProperty PATTR = new ZipNodeProperty(ATTR);
+       public final static ZipNodeProperty PCOMMENT = new ZipNodeProperty(COMMENT);
+
+       private ZipNodeProperty(int type) {
+               super(type);
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/operations/AddOperation.java b/org.tizen.common.externals/src/zipeditor/operations/AddOperation.java
new file mode 100644 (file)
index 0000000..4a227f4
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.operations;
+
+import java.io.File;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.ui.progress.UIJob;
+
+import zipeditor.Messages;
+import zipeditor.Utils;
+import zipeditor.ZipEditorPlugin;
+import zipeditor.model.Node;
+
+public class AddOperation {
+       private class AddFilesJob extends Job {
+               private String[] fFilesNames;
+               private Node fParentNode;
+               private Node fBeforeSibling;
+               private boolean fAtLeastOneAdded;
+               private UIJob fRefreshJob;
+
+               public AddFilesJob(String[] filesNames, Node parentNode, Node beforeSibling, UIJob refreshJob) {
+                       super(Messages.getString("AddOperation.1")); //$NON-NLS-1$
+                       fFilesNames = filesNames;
+                       fParentNode = parentNode;
+                       fBeforeSibling = beforeSibling;
+                       fRefreshJob = refreshJob;
+               }
+
+               public IStatus run(IProgressMonitor monitor) {
+                       monitor.beginTask(Messages.getString("AddOperation.4"), 100); //$NON-NLS-1$
+                       monitor.worked(1);
+                       int totalWork = Utils.computeTotalNumber(getFilesFromNames(fFilesNames), monitor);
+                       monitor.setTaskName(Messages.getString("AddOperation.2")); //$NON-NLS-1$
+                       SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, 99);
+                       subMonitor.beginTask(Messages.getString("AddOperation.2"), totalWork); //$NON-NLS-1$
+                       try {
+                               boolean oneAdded = false;
+                               for (int i = 0; i < fFilesNames.length; i++) {
+                                       if (subMonitor.isCanceled())
+                                               break;
+                                       try {
+                                               fParentNode.add(new File(fFilesNames[i]), fBeforeSibling, subMonitor);
+                                               oneAdded = true;
+                                       } catch (Exception e) {
+                                               return ZipEditorPlugin.createErrorStatus(Messages.getString("AddOperation.0"), e); //$NON-NLS-1$
+                                       }
+                                       subMonitor.worked(1);
+                               }
+                               if (oneAdded) {
+                                       fRefreshJob.schedule();
+                               }
+                       } finally {
+                               subMonitor.done();
+                               monitor.done();
+                       }
+                       return Status.OK_STATUS;
+               }
+
+               public boolean atLeastOneAdded() {
+                       return fAtLeastOneAdded;
+               }
+       };
+       
+       private class RefreshJob extends UIJob {
+               private StructuredViewer fViewer;
+
+               public RefreshJob(StructuredViewer viewer) {
+                       super(Messages.getString("AddOperation.3")); //$NON-NLS-1$
+                       fViewer = viewer;
+               }
+
+               public IStatus runInUIThread(IProgressMonitor monitor) {
+                       if (!fViewer.getControl().isDisposed()) {
+                               fViewer.refresh();
+                       }
+                       return Status.OK_STATUS;
+               }
+       };
+       
+       public void execute(String[] fileNames, Node parentNode, Node beforeSibling, StructuredViewer viewer) {
+               
+               while (parentNode != null && !parentNode.isFolder())
+                       parentNode = parentNode.getParent();
+               AddFilesJob addFilesJob = new AddFilesJob(fileNames, parentNode, beforeSibling, new RefreshJob(viewer));
+               addFilesJob.schedule();
+       }
+
+       private File[] getFilesFromNames(String[] filesNames) {
+               File[] files = new File[filesNames.length];
+               for (int i = 0; i < files.length; i++) {
+                       files[i] = new File(filesNames[i]);
+               }
+               return files;
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/operations/ExtractOperation.java b/org.tizen.common.externals/src/zipeditor/operations/ExtractOperation.java
new file mode 100644 (file)
index 0000000..de78be4
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.operations;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+
+import zipeditor.Messages;
+import zipeditor.Utils;
+import zipeditor.ZipEditorPlugin;
+import zipeditor.model.Node;
+import zipeditor.model.ZipModel;
+
+public class ExtractOperation {
+       private class ExtractJob extends Job {
+               private Node[] fNodes;
+               private File fTargetDir;
+               private boolean fOverwrite;
+
+               public ExtractJob(Node[] nodes, File targetDir) {
+                       super(Messages.getString("ExtractOperation.0")); //$NON-NLS-1$
+                       fNodes = nodes;
+                       fTargetDir = targetDir;
+               }
+               
+               protected IStatus run(IProgressMonitor monitor) {
+                       monitor.beginTask(Messages.getString("ExtractOperation.1"), Utils.computeTotalNumber(fNodes, monitor)); //$NON-NLS-1$
+                       extract(fNodes, fTargetDir, fOverwrite, false, monitor);
+                       if (fRefreshJob != null)
+                               fRefreshJob.schedule();
+                       return Status.OK_STATUS;
+               }
+               
+               public boolean belongsTo(Object family) {
+                       return family == ExtractFamily;
+               }
+       };
+       
+       public static final Object ExtractFamily = new Object();
+
+       public static class ExtractRule implements ISchedulingRule {
+               public boolean contains(ISchedulingRule rule) {
+                       return rule instanceof ExtractRule;
+               }
+
+               public boolean isConflicting(ISchedulingRule rule) {
+                       return rule instanceof ExtractRule;
+               }
+       };
+       
+       private Job fRefreshJob;
+       private int fUserStatus = ASK;
+       
+       private final static int ASK = 0x01;
+       private final static int OVERRIDE = 0x02;
+
+       private final static Set extracting = new HashSet();
+
+       public File execute(Node[] nodes, File toDir, boolean inBackground, boolean overwrite) {
+               return inBackground ? extractInBackground(nodes, toDir) :
+                       extract(nodes, toDir, overwrite, false, new NullProgressMonitor());
+       }
+       
+       public void setRefreshJob(Job refreshJob) {
+               fRefreshJob = refreshJob;
+       }
+       
+       private File extractInBackground(Node[] nodes, File toDir) {
+               if (nodes == null || nodes.length == 0)
+                       return toDir;
+               File targetDir = determineFolderTarget(toDir != null ? toDir : nodes[0].getModel().getTempDir());
+               ExtractJob job = new ExtractJob(nodes, targetDir);
+               job.setRule(new ExtractRule());
+               job.schedule();
+               return targetDir;
+       }
+
+       public File extract(Node node, File toDir, boolean overwrite, IProgressMonitor monitor) {
+               return internalExtract(node, toDir, overwrite, true, monitor);
+       }
+
+       private File internalExtract(Node node, File toDir, boolean overwrite, boolean fullNodePath, IProgressMonitor monitor) {
+               if (monitor.isCanceled())
+                       return null;
+               toDir = determineFolderTarget(toDir);
+               File file = null;
+               if (node.isFolder()) {
+                       file = fullNodePath ? toDir : new File(toDir, node.getName());
+                       if (!file.exists())
+                               file.mkdirs();
+                       Node[] children = node.getChildren();
+                       for (int i = 0; i < children.length; i++) {
+                               internalExtract(children[i], file, overwrite, fullNodePath, monitor);
+                       }
+               } else {
+                       file = new File(toDir, fullNodePath ? node.getFullPath() : node.getName());
+                       while (extracting.contains(file)) {
+                               try {
+                                       Thread.sleep(100);
+                               } catch (InterruptedException e) {
+                                       break;
+                               }
+                       }
+                       boolean writeFile = !file.exists();
+                       if (!writeFile && !overwrite && (fUserStatus & ASK) > 0 && !isTempFolder(toDir, node.getModel())) {
+                               switch (showWarning(file)) {
+                               case 0:
+                                       writeFile = true;
+                                       break;
+                               case 1:
+                                       writeFile = true;
+                                       fUserStatus &= -1 ^ ASK;
+                                       fUserStatus |= OVERRIDE;
+                                       break;
+                               case 3:
+                                       fUserStatus &= -1 ^ (ASK | OVERRIDE);
+                                       break;
+                               case 4:
+                                       monitor.setCanceled(true);
+                                       return file;
+                               }
+                       }
+                       if (writeFile || (fUserStatus & OVERRIDE) > 0) {
+                               File parent = file.getParentFile();
+                               if (!parent.exists())
+                                       parent.mkdirs();
+                               monitor.subTask(file.getName());
+                               try {
+                                       extracting.add(file);
+                                       long time = System.currentTimeMillis();
+                                       Utils.readAndWrite(node.getContent(), new FileOutputStream(file), true);
+                                       if (ZipEditorPlugin.DEBUG)
+                                               System.out.println("Extracted " + node + " in " + (System.currentTimeMillis() - time) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                               } catch (Exception e) {
+                                       node.getModel().logError(e);
+                               } finally {
+                                       extracting.remove(file);
+                               }
+                       }
+                       monitor.worked(1);
+               }
+               return file;
+       }
+       
+       private int showWarning(final File file) {
+               if (Utils.isUIThread()) {
+                       return doShowWarning(file);
+               } else {
+                       final int[] result = { -1 };
+                       Display.getDefault().syncExec(new Runnable() {
+                               public void run() {
+                                       result[0] = doShowWarning(file);
+                               }
+                       });
+                       return result[0];
+               }
+       }
+       
+       private int doShowWarning(File file) {
+               MessageDialog dialog = new MessageDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+                               Messages.getString("ExtractOperation.2"), //$NON-NLS-1$
+                               null, Messages.getFormattedString("ExtractOperation.3", file.getAbsolutePath()), //$NON-NLS-1$
+                               MessageDialog.QUESTION,
+                               new String[] { IDialogConstants.YES_LABEL, IDialogConstants.YES_TO_ALL_LABEL,
+                               IDialogConstants.NO_LABEL, IDialogConstants.NO_TO_ALL_LABEL, IDialogConstants.CANCEL_LABEL },
+                               0);
+               return dialog.open();
+       }
+       
+       private boolean isTempFolder(File toDir, ZipModel model) {
+               File tmp = model.getTempDir();
+               return toDir.getAbsolutePath().startsWith(tmp.getAbsolutePath());
+       }
+
+       public File extract(Node[] nodes, File toDir, boolean overwrite, boolean fullNodePath, IProgressMonitor monitor) {
+               if (nodes == null || nodes.length == 0)
+                       return toDir;
+               File targetDir = determineFolderTarget(toDir != null ? toDir : nodes[0].getModel().getTempDir());
+               for (int i = 0; i < nodes.length; i++) {
+                       internalExtract(nodes[i], targetDir, overwrite, fullNodePath, monitor);
+               }
+               return toDir;
+       }
+
+       private File determineFolderTarget(File file) {
+               while (file != null && !file.isDirectory())
+                       file = file.getParentFile();
+               return file;
+       }
+}
diff --git a/org.tizen.common.externals/src/zipeditor/operations/OpenFileOperation.java b/org.tizen.common.externals/src/zipeditor/operations/OpenFileOperation.java
new file mode 100644 (file)
index 0000000..bd1dcae
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * (c) Copyright 2002, 2005 Uwe Voigt
+ * All Rights Reserved.
+ */
+package zipeditor.operations;
+
+import java.io.File;
+
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.tizen.common.util.FilenameUtil;
+
+import zipeditor.Messages;
+import zipeditor.Utils;
+import zipeditor.ZipEditorPlugin;
+
+public class OpenFileOperation {
+    private final Logger logger = LoggerFactory.getLogger(OpenFileOperation.class);
+    public IEditorPart execute(File file) {
+        IFileStore fileStore = Utils.getFileStore(file);
+        if (!fileStore.fetchInfo().isDirectory() && fileStore.fetchInfo().exists()) {
+            file.setReadOnly();
+            final IEditorInput input = Utils.createEditorInput(fileStore);
+
+            String editorId = null;
+            String inputFileName = input.getName();
+            
+            if ( "xml".equals(FilenameUtil.getExtension(inputFileName).toLowerCase()) ) {
+                try {
+                    editorId = IDE.getEditorDescriptor("*.xml").getId();
+                } catch (PartInitException e) {
+                    logger.error("Cannot get editor id for xml file", e);
+                }
+            }
+            if ( editorId == null ) {
+                editorId = Utils.getEditorId(fileStore);
+            }
+
+            if (Utils.isUIThread()) {
+                return openEditor(input, editorId);
+            } else {
+                final IEditorPart[] result = { null };
+                final String finalEditorId = editorId;
+                Display.getDefault().syncExec(new Runnable() {
+                    public void run() {
+                        result[0] = openEditor(input, finalEditorId);
+                    }
+                });
+                return result[0];
+            }
+        }
+        return null;
+    }
+
+    private IEditorPart openEditor(IEditorInput input, String editorId) {
+        IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+
+        try {
+            return page.openEditor(input, editorId);
+        } catch (PartInitException e) {
+            ZipEditorPlugin.log(e);
+            MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), Messages.getString("ZipEditor.8"), e.getMessage()); //$NON-NLS-1$
+            return null;
+        }
+    }
+
+}
index bcf55cd..fe7a610 100644 (file)
@@ -52,6 +52,7 @@ public class TizenPlatformConstants {
     public static final String PACKAGENAME_PREFIX = "org.tizen";
     public static final String DEBIAN_INSTALL_PATH = "opt/*";
     public static final String PKGTYPE_TPK = "TPK";
+    public static final String PKGTYPE_WGT = "WGT";
     public static final String PKGTYPE_RPM = "RPM";
     public static final String PKGTYPE_DEB = "DEB";