mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-01 05:15:43 +02:00
Bug 196337 - Initial contribution of local terminal feature
This commit is contained in:
parent
d336005626
commit
dd398b77bb
41 changed files with 4154 additions and 0 deletions
17
org.eclipse.tm.terminal.local-feature/.project
Normal file
17
org.eclipse.tm.terminal.local-feature/.project
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>org.eclipse.tm.terminal.local-feature</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.FeatureBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.pde.FeatureNature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
15
org.eclipse.tm.terminal.local-feature/build.properties
Normal file
15
org.eclipse.tm.terminal.local-feature/build.properties
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
####################################################################################################
|
||||||
|
# Copyright (c) 2008 Mirko Raner 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:
|
||||||
|
# Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
####################################################################################################
|
||||||
|
|
||||||
|
bin.includes = feature.xml,\
|
||||||
|
feature.properties,\
|
||||||
|
epl-v10.html,\
|
||||||
|
license.html
|
256
org.eclipse.tm.terminal.local-feature/epl-v10.html
Normal file
256
org.eclipse.tm.terminal.local-feature/epl-v10.html
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"><head>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Eclipse Public License - Version 1.0</title>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
size: 8.5in 11.0in;
|
||||||
|
margin: 0.25in 0.5in 0.25in 0.5in;
|
||||||
|
tab-interval: 0.5in;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
p.list {
|
||||||
|
margin-left: 0.5in;
|
||||||
|
margin-top: 0.05em;
|
||||||
|
margin-bottom: 0.05em;
|
||||||
|
}
|
||||||
|
</style></head><body lang="EN-US">
|
||||||
|
|
||||||
|
<p align="center"><b>Eclipse Public License - v 1.0</b></p>
|
||||||
|
|
||||||
|
<p>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
|
||||||
|
PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR
|
||||||
|
DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS
|
||||||
|
AGREEMENT.</p>
|
||||||
|
|
||||||
|
<p><b>1. DEFINITIONS</b></p>
|
||||||
|
|
||||||
|
<p>"Contribution" means:</p>
|
||||||
|
|
||||||
|
<p class="list">a) in the case of the initial Contributor, the initial
|
||||||
|
code and documentation distributed under this Agreement, and</p>
|
||||||
|
<p class="list">b) in the case of each subsequent Contributor:</p>
|
||||||
|
<p class="list">i) changes to the Program, and</p>
|
||||||
|
<p class="list">ii) additions to the Program;</p>
|
||||||
|
<p class="list">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.</p>
|
||||||
|
|
||||||
|
<p>"Contributor" means any person or entity that distributes
|
||||||
|
the Program.</p>
|
||||||
|
|
||||||
|
<p>"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.</p>
|
||||||
|
|
||||||
|
<p>"Program" means the Contributions distributed in accordance
|
||||||
|
with this Agreement.</p>
|
||||||
|
|
||||||
|
<p>"Recipient" means anyone who receives the Program under
|
||||||
|
this Agreement, including all Contributors.</p>
|
||||||
|
|
||||||
|
<p><b>2. GRANT OF RIGHTS</b></p>
|
||||||
|
|
||||||
|
<p class="list">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.</p>
|
||||||
|
|
||||||
|
<p class="list">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.</p>
|
||||||
|
|
||||||
|
<p class="list">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.</p>
|
||||||
|
|
||||||
|
<p class="list">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.</p>
|
||||||
|
|
||||||
|
<p><b>3. REQUIREMENTS</b></p>
|
||||||
|
|
||||||
|
<p>A Contributor may choose to distribute the Program in object code
|
||||||
|
form under its own license agreement, provided that:</p>
|
||||||
|
|
||||||
|
<p class="list">a) it complies with the terms and conditions of this
|
||||||
|
Agreement; and</p>
|
||||||
|
|
||||||
|
<p class="list">b) its license agreement:</p>
|
||||||
|
|
||||||
|
<p class="list">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;</p>
|
||||||
|
|
||||||
|
<p class="list">ii) effectively excludes on behalf of all Contributors
|
||||||
|
all liability for damages, including direct, indirect, special,
|
||||||
|
incidental and consequential damages, such as lost profits;</p>
|
||||||
|
|
||||||
|
<p class="list">iii) states that any provisions which differ from this
|
||||||
|
Agreement are offered by that Contributor alone and not by any other
|
||||||
|
party; and</p>
|
||||||
|
|
||||||
|
<p class="list">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.</p>
|
||||||
|
|
||||||
|
<p>When the Program is made available in source code form:</p>
|
||||||
|
|
||||||
|
<p class="list">a) it must be made available under this Agreement; and</p>
|
||||||
|
|
||||||
|
<p class="list">b) a copy of this Agreement must be included with each
|
||||||
|
copy of the Program.</p>
|
||||||
|
|
||||||
|
<p>Contributors may not remove or alter any copyright notices contained
|
||||||
|
within the Program.</p>
|
||||||
|
|
||||||
|
<p>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.</p>
|
||||||
|
|
||||||
|
<p><b>4. COMMERCIAL DISTRIBUTION</b></p>
|
||||||
|
|
||||||
|
<p>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.</p>
|
||||||
|
|
||||||
|
<p>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.</p>
|
||||||
|
|
||||||
|
<p><b>5. NO WARRANTY</b></p>
|
||||||
|
|
||||||
|
<p>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.</p>
|
||||||
|
|
||||||
|
<p><b>6. DISCLAIMER OF LIABILITY</b></p>
|
||||||
|
|
||||||
|
<p>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.</p>
|
||||||
|
|
||||||
|
<p><b>7. GENERAL</b></p>
|
||||||
|
|
||||||
|
<p>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.</p>
|
||||||
|
|
||||||
|
<p>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.</p>
|
||||||
|
|
||||||
|
<p>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.</p>
|
||||||
|
|
||||||
|
<p>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. The Eclipse
|
||||||
|
Foundation is the initial Agreement Steward. The Eclipse Foundation 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.</p>
|
||||||
|
|
||||||
|
<p>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.</p>
|
||||||
|
|
||||||
|
</body></html>
|
117
org.eclipse.tm.terminal.local-feature/feature.properties
Normal file
117
org.eclipse.tm.terminal.local-feature/feature.properties
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
####################################################################################################
|
||||||
|
# Copyright (c) 2008 Mirko Raner 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:
|
||||||
|
# Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
####################################################################################################
|
||||||
|
|
||||||
|
featureName=Target Management Terminal Local Connector
|
||||||
|
description=A local connector implementation for the Terminal.
|
||||||
|
copyright=\
|
||||||
|
Copyright (c) 2008 Mirko Raner and others.\n\
|
||||||
|
All rights reserved. This program and the accompanying materials\n\
|
||||||
|
are made available under the terms of the Eclipse Public License v1.0\n\
|
||||||
|
which accompanies this distribution, and is available at\n\
|
||||||
|
http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
licenseURL=license.html
|
||||||
|
license=\
|
||||||
|
ECLIPSE FOUNDATION SOFTWARE USER AGREEMENT\n\
|
||||||
|
March 17, 2005\n\
|
||||||
|
\n\
|
||||||
|
Usage Of Content\n\
|
||||||
|
\n\
|
||||||
|
THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR\n\
|
||||||
|
OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT").\n\
|
||||||
|
USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS\n\
|
||||||
|
AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR\n\
|
||||||
|
NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU\n\
|
||||||
|
AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT\n\
|
||||||
|
AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS\n\
|
||||||
|
OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE\n\
|
||||||
|
TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS\n\
|
||||||
|
OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\
|
||||||
|
BELOW, THEN YOU MAY NOT USE THE CONTENT.\n\
|
||||||
|
\n\
|
||||||
|
Applicable Licenses\n\
|
||||||
|
\n\
|
||||||
|
Unless otherwise indicated, all Content made available by the Eclipse Foundation\n\
|
||||||
|
is provided to you under the terms and conditions of the Eclipse Public\n\
|
||||||
|
License Version 1.0 ("EPL"). A copy of the EPL is provided with this\n\
|
||||||
|
Content and is also available at http://www.eclipse.org/legal/epl-v10.html.\n\
|
||||||
|
For purposes of the EPL, "Program" will mean the Content.\n\
|
||||||
|
\n\
|
||||||
|
Content includes, but is not limited to, source code, object code,\n\
|
||||||
|
documentation and other files maintained in the Eclipse.org CVS\n\
|
||||||
|
repository ("Repository") in CVS modules ("Modules") and made available\n\
|
||||||
|
as downloadable archives ("Downloads").\n\
|
||||||
|
\n\
|
||||||
|
- Content may be structured and packaged into modules to facilitate delivering,\n\
|
||||||
|
extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"),\n\
|
||||||
|
plug-in fragments ("Fragments"), and features ("Features").\n\
|
||||||
|
- Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java(TM) ARchive)\n\
|
||||||
|
in a directory named "plugins".\n\
|
||||||
|
- A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.\n\
|
||||||
|
Each Feature may be packaged as a sub-directory in a directory named "features".\n\
|
||||||
|
Within a Feature, files named "feature.xml" may contain a list of the names and version\n\
|
||||||
|
numbers of the Plug-ins and/or Fragments associated with that Feature.\n\
|
||||||
|
- Features may also include other Features ("Included Features"). Within a Feature, files\n\
|
||||||
|
named "feature.xml" may contain a list of the names and version numbers of Included Features.\n\
|
||||||
|
\n\
|
||||||
|
Features may also include other Features ("Included Features"). Files named\n\
|
||||||
|
"feature.xml" may contain a list of the names and version numbers of\n\
|
||||||
|
Included Features.\n\
|
||||||
|
\n\
|
||||||
|
The terms and conditions governing Plug-ins and Fragments should be\n\
|
||||||
|
contained in files named "about.html" ("Abouts"). The terms and\n\
|
||||||
|
conditions governing Features and Included Features should be contained\n\
|
||||||
|
in files named "license.html" ("Feature Licenses"). Abouts and Feature\n\
|
||||||
|
Licenses may be located in any directory of a Download or Module\n\
|
||||||
|
including, but not limited to the following locations:\n\
|
||||||
|
\n\
|
||||||
|
- The top-level (root) directory\n\
|
||||||
|
- Plug-in and Fragment directories\n\
|
||||||
|
- Inside Plug-ins and Fragments packaged as JARs\n\
|
||||||
|
- Sub-directories of the directory named "src" of certain Plug-ins\n\
|
||||||
|
- Feature directories\n\
|
||||||
|
\n\
|
||||||
|
Note: if a Feature made available by the Eclipse Foundation is installed using the\n\
|
||||||
|
Eclipse Update Manager, you must agree to a license ("Feature Update\n\
|
||||||
|
License") during the installation process. If the Feature contains\n\
|
||||||
|
Included Features, the Feature Update License should either provide you\n\
|
||||||
|
with the terms and conditions governing the Included Features or inform\n\
|
||||||
|
you where you can locate them. Feature Update Licenses may be found in\n\
|
||||||
|
the "license" property of files named "feature.properties". Such Abouts,\n\
|
||||||
|
Feature Licenses and Feature Update Licenses contain the terms and\n\
|
||||||
|
conditions (or references to such terms and conditions) that govern your\n\
|
||||||
|
use of the associated Content in that directory.\n\
|
||||||
|
\n\
|
||||||
|
THE ABOUTS, FEATURE LICENSES AND FEATURE UPDATE LICENSES MAY REFER\n\
|
||||||
|
TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.\n\
|
||||||
|
SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\
|
||||||
|
\n\
|
||||||
|
- Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\
|
||||||
|
- Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\
|
||||||
|
- Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\
|
||||||
|
- IBM Public License 1.0 (available at http://oss.software.ibm.com/developerworks/opensource/license10.html)\n\
|
||||||
|
- Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\
|
||||||
|
- Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\
|
||||||
|
\n\
|
||||||
|
IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\
|
||||||
|
TO USE OF THE CONTENT. If no About, Feature License or Feature Update License\n\
|
||||||
|
is provided, please contact the Eclipse Foundation to determine what terms and conditions\n\
|
||||||
|
govern that particular Content.\n\
|
||||||
|
\n\
|
||||||
|
Cryptography\n\
|
||||||
|
\n\
|
||||||
|
Content may contain encryption software. The country in which you are\n\
|
||||||
|
currently may have restrictions on the import, possession, and use,\n\
|
||||||
|
and/or re-export to another country, of encryption software. BEFORE\n\
|
||||||
|
using any encryption software, please check the country's laws,\n\
|
||||||
|
regulations and policies concerning the import, possession, or use,\n\
|
||||||
|
and re-export of encryption software, to see if this is permitted.\n\
|
||||||
|
\n\
|
||||||
|
Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.\n
|
47
org.eclipse.tm.terminal.local-feature/feature.xml
Normal file
47
org.eclipse.tm.terminal.local-feature/feature.xml
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
# Copyright (c) 2008 Mirko Raner 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:
|
||||||
|
# Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
-->
|
||||||
|
<feature id="org.eclipse.tm.terminal.local"
|
||||||
|
label="%featureName"
|
||||||
|
version="1.0.0.qualifier"
|
||||||
|
provider-name="Mirko Raner">
|
||||||
|
|
||||||
|
<description>
|
||||||
|
%description
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<copyright>
|
||||||
|
%copyright
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<license url="%licenseURL">
|
||||||
|
%license
|
||||||
|
</license>
|
||||||
|
|
||||||
|
<requires>
|
||||||
|
<import plugin="org.eclipse.tm.terminal" version="2.0.0" match="compatible"/>
|
||||||
|
<import plugin="org.eclipse.cdt.core" version="5.0.0" match="compatible"/>
|
||||||
|
<import plugin="org.eclipse.core.runtime"/>
|
||||||
|
<import plugin="org.eclipse.debug.core"/>
|
||||||
|
<import plugin="org.eclipse.debug.ui"/>
|
||||||
|
<import plugin="org.eclipse.jface"/>
|
||||||
|
<import plugin="org.eclipse.ui"/>
|
||||||
|
<import plugin="org.eclipse.ui.externaltools"/>
|
||||||
|
</requires>
|
||||||
|
|
||||||
|
<plugin id="org.eclipse.tm.terminal.local"
|
||||||
|
download-size="0"
|
||||||
|
install-size="0"
|
||||||
|
version="0.0.0"
|
||||||
|
unpack="false"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</feature>
|
79
org.eclipse.tm.terminal.local-feature/license.html
Normal file
79
org.eclipse.tm.terminal.local-feature/license.html
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv=Content-Type content="text/html; charset=iso-8859-1">
|
||||||
|
<title>Eclipse.org Software User Agreement</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body lang="EN-US" link=blue vlink=purple>
|
||||||
|
<h2>Eclipse Foundation Software User Agreement</h2>
|
||||||
|
<p>March 17, 2005</p>
|
||||||
|
|
||||||
|
<h3>Usage Of Content</h3>
|
||||||
|
|
||||||
|
<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
|
||||||
|
(COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
|
||||||
|
CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE
|
||||||
|
OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
|
||||||
|
NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
|
||||||
|
CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
|
||||||
|
|
||||||
|
<h3>Applicable Licenses</h3>
|
||||||
|
|
||||||
|
<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
|
||||||
|
("EPL"). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
|
||||||
|
For purposes of the EPL, "Program" will mean the Content.</p>
|
||||||
|
|
||||||
|
<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse.org CVS repository ("Repository") in CVS
|
||||||
|
modules ("Modules") and made available as downloadable archives ("Downloads").</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li>
|
||||||
|
<li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li>
|
||||||
|
<li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins
|
||||||
|
and/or Fragments associated with that Feature.</li>
|
||||||
|
<li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and
|
||||||
|
Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module
|
||||||
|
including, but not limited to the following locations:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>The top-level (root) directory</li>
|
||||||
|
<li>Plug-in and Fragment directories</li>
|
||||||
|
<li>Inside Plug-ins and Fragments packaged as JARs</li>
|
||||||
|
<li>Sub-directories of the directory named "src" of certain Plug-ins</li>
|
||||||
|
<li>Feature directories</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Eclipse Update Manager, you must agree to a license ("Feature Update License") during the
|
||||||
|
installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
|
||||||
|
inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature.
|
||||||
|
Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
|
||||||
|
that directory.</p>
|
||||||
|
|
||||||
|
<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE
|
||||||
|
OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
|
||||||
|
<li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
|
||||||
|
<li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
|
||||||
|
<li>IBM Public License 1.0 (available at <a href="http://oss.software.ibm.com/developerworks/opensource/license10.html">http://oss.software.ibm.com/developerworks/opensource/license10.html</a>)</li>
|
||||||
|
<li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li>
|
||||||
|
<li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License is provided, please
|
||||||
|
contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
|
||||||
|
|
||||||
|
<h3>Cryptography</h3>
|
||||||
|
|
||||||
|
<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
|
||||||
|
another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
|
||||||
|
possession, or use, and re-export of encryption software, to see if this is permitted.</p>
|
||||||
|
|
||||||
|
<small>Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.</small>
|
||||||
|
</body>
|
||||||
|
</html>
|
7
org.eclipse.tm.terminal.local/.classpath
Normal file
7
org.eclipse.tm.terminal.local/.classpath
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
28
org.eclipse.tm.terminal.local/.project
Normal file
28
org.eclipse.tm.terminal.local/.project
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>org.eclipse.tm.terminal.local</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.pde.PluginNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
|
@ -0,0 +1,83 @@
|
||||||
|
#Tue Jul 29 00:26:52 PDT 2008
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.4
|
||||||
|
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||||
|
org.eclipse.jdt.core.compiler.doc.comment.support=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.autoboxing=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.deprecation=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.discouragedReference=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected
|
||||||
|
org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected
|
||||||
|
org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=all_standard_tags
|
||||||
|
org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=protected
|
||||||
|
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.nullReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.3
|
20
org.eclipse.tm.terminal.local/META-INF/MANIFEST.MF
Normal file
20
org.eclipse.tm.terminal.local/META-INF/MANIFEST.MF
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
Manifest-Version: 1.0
|
||||||
|
Bundle-ManifestVersion: 2
|
||||||
|
Bundle-Name: %pluginName
|
||||||
|
Bundle-SymbolicName: org.eclipse.tm.terminal.local;singleton:=true
|
||||||
|
Bundle-Version: 1.0.0
|
||||||
|
Bundle-Activator: org.eclipse.tm.internal.terminal.local.LocalTerminalActivator
|
||||||
|
Bundle-Localization: plugin
|
||||||
|
Bundle-Vendor: %providerName
|
||||||
|
Require-Bundle: org.eclipse.tm.terminal;bundle-version="2.0.0",
|
||||||
|
org.eclipse.cdt.core;bundle-version="5.0.0",
|
||||||
|
org.eclipse.core.runtime,
|
||||||
|
org.eclipse.debug.core,
|
||||||
|
org.eclipse.debug.ui,
|
||||||
|
org.eclipse.jface,
|
||||||
|
org.eclipse.ui,
|
||||||
|
org.eclipse.ui.externaltools
|
||||||
|
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
||||||
|
Bundle-ActivationPolicy: lazy
|
||||||
|
Eclipse-LazyStart: true
|
||||||
|
Import-Package: org.eclipse.core.variables
|
37
org.eclipse.tm.terminal.local/about.html
Normal file
37
org.eclipse.tm.terminal.local/about.html
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||||
|
<!--
|
||||||
|
# Copyright (c) 2008 Mirko Raner 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:
|
||||||
|
# Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
-->
|
||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<TITLE>About</TITLE>
|
||||||
|
<META HTTP-EQUIV=Content-Type CONTENT="text/html; charset=ISO-8859-1">
|
||||||
|
</HEAD>
|
||||||
|
<BODY LANG="EN-US">
|
||||||
|
<H2>About This Content</H2>
|
||||||
|
<P>
|
||||||
|
August 4, 2008
|
||||||
|
<P>
|
||||||
|
<H3>License</H3>
|
||||||
|
|
||||||
|
Mirko Raner makes available all content in this plug-in ("Content").
|
||||||
|
Unless otherwise indicated below, the Content is provided to you under the terms and conditions of
|
||||||
|
the Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available at
|
||||||
|
<A HREF="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</A>.
|
||||||
|
For purposes of the EPL, "Program" will mean the Content.
|
||||||
|
<P>
|
||||||
|
If you did not receive this Content directly from Mirko Raner, the Content is
|
||||||
|
being redistributed by another party ("Redistributor") and different terms and
|
||||||
|
conditions may apply to your use of any object code in the Content. Check the Redistributor's
|
||||||
|
license that was provided with the Content. If no such license exists, contact the Redistributor.
|
||||||
|
Unless otherwise indicated below, the terms and conditions of the EPL still apply to any source
|
||||||
|
code in the Content.
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
13
org.eclipse.tm.terminal.local/about.ini
Normal file
13
org.eclipse.tm.terminal.local/about.ini
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
####################################################################################################
|
||||||
|
# Copyright (c) 2008 Mirko Raner 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:
|
||||||
|
# Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
####################################################################################################
|
||||||
|
|
||||||
|
featureImage=icons/terminal-local.png
|
||||||
|
aboutText=%feature.information
|
12
org.eclipse.tm.terminal.local/about.mappings
Normal file
12
org.eclipse.tm.terminal.local/about.mappings
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
####################################################################################################
|
||||||
|
# Copyright (c) 2008 Mirko Raner 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:
|
||||||
|
# Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
####################################################################################################
|
||||||
|
|
||||||
|
0=@build@
|
17
org.eclipse.tm.terminal.local/about.properties
Normal file
17
org.eclipse.tm.terminal.local/about.properties
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
####################################################################################################
|
||||||
|
# Copyright (c) 2008 Mirko Raner 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:
|
||||||
|
# Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
####################################################################################################
|
||||||
|
|
||||||
|
feature.information=Target Management Terminal Local Connector\n\
|
||||||
|
\n\
|
||||||
|
Version: {featureVersion}\n\
|
||||||
|
\n\
|
||||||
|
(c) Copyright Mirko Raner and others, 2008. All rights reserved.\n\
|
||||||
|
Visit http://www.eclipse.org/dsdp/tm
|
11
org.eclipse.tm.terminal.local/build.properties
Normal file
11
org.eclipse.tm.terminal.local/build.properties
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
source.. = src/
|
||||||
|
output.. = bin/
|
||||||
|
bin.includes = plugin.xml,\
|
||||||
|
plugin.properties,\
|
||||||
|
about.html,\
|
||||||
|
about.ini,\
|
||||||
|
about.mappings,\
|
||||||
|
about.properties,\
|
||||||
|
icons/,\
|
||||||
|
META-INF/,\
|
||||||
|
.
|
BIN
org.eclipse.tm.terminal.local/icons/terminal-launch.gif
Normal file
BIN
org.eclipse.tm.terminal.local/icons/terminal-launch.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 601 B |
BIN
org.eclipse.tm.terminal.local/icons/terminal-local.png
Normal file
BIN
org.eclipse.tm.terminal.local/icons/terminal-local.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
16
org.eclipse.tm.terminal.local/plugin.properties
Normal file
16
org.eclipse.tm.terminal.local/plugin.properties
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
####################################################################################################
|
||||||
|
# Copyright (c) 2008 Mirko Raner 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:
|
||||||
|
# Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
####################################################################################################
|
||||||
|
|
||||||
|
pluginName=Local Terminal Connector
|
||||||
|
providerName=Mirko Raner
|
||||||
|
terminalLaunch=Terminal
|
||||||
|
terminalLaunchDescription=Run a program in a terminal
|
||||||
|
localConnection=Local program
|
63
org.eclipse.tm.terminal.local/plugin.xml
Normal file
63
org.eclipse.tm.terminal.local/plugin.xml
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<?eclipse version="3.3"?>
|
||||||
|
<!--
|
||||||
|
# Copyright (c) 2008 Mirko Raner 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:
|
||||||
|
# Mirko Raner - initial API and implementation
|
||||||
|
-->
|
||||||
|
<plugin>
|
||||||
|
|
||||||
|
<!-- Terminal connector extension (the primary contribution of this plug-in): -->
|
||||||
|
<!-- -->
|
||||||
|
<extension point="org.eclipse.tm.terminal.terminalConnectors">
|
||||||
|
<connector name="%localConnection"
|
||||||
|
id="org.eclipse.tm.internal.terminal.local.LocalTerminalConnector"
|
||||||
|
class="org.eclipse.tm.internal.terminal.local.LocalTerminalConnector"
|
||||||
|
/>
|
||||||
|
</extension>
|
||||||
|
|
||||||
|
<!-- Process factory for terminal processes (necessary for preventing a standard console from -->
|
||||||
|
<!-- being created): -->
|
||||||
|
<!-- -->
|
||||||
|
<extension point="org.eclipse.debug.core.processFactories">
|
||||||
|
<processFactory id="org.eclipse.tm.terminal.localProcess.factory"
|
||||||
|
class="org.eclipse.tm.internal.terminal.local.process.LocalTerminalProcessFactory"
|
||||||
|
/>
|
||||||
|
</extension>
|
||||||
|
|
||||||
|
<!-- Launch configuration type for terminal launches: -->
|
||||||
|
<!-- -->
|
||||||
|
<extension point="org.eclipse.debug.core.launchConfigurationTypes">
|
||||||
|
<launchConfigurationType name="%terminalLaunch"
|
||||||
|
id="org.eclipse.tm.terminal.local.launch"
|
||||||
|
delegate="org.eclipse.tm.internal.terminal.local.launch.LocalTerminalLaunchDelegate"
|
||||||
|
category="org.eclipse.ui.externaltools"
|
||||||
|
modes="run"
|
||||||
|
/>
|
||||||
|
</extension>
|
||||||
|
|
||||||
|
<!-- Launch configuration icon used in the Launch Configuration dialog: -->
|
||||||
|
<!-- -->
|
||||||
|
<extension point="org.eclipse.debug.ui.launchConfigurationTypeImages">
|
||||||
|
<launchConfigurationTypeImage id="org.eclipse.tm.terminal.local.launch.icon"
|
||||||
|
configTypeID="org.eclipse.tm.terminal.local.launch"
|
||||||
|
icon="icons/terminal-launch.gif"
|
||||||
|
/>
|
||||||
|
</extension>
|
||||||
|
|
||||||
|
<!-- Launch configuration tab group for configuring workbench launches: -->
|
||||||
|
<!-- -->
|
||||||
|
<extension point="org.eclipse.debug.ui.launchConfigurationTabGroups">
|
||||||
|
<launchConfigurationTabGroup type="org.eclipse.tm.terminal.local.launch"
|
||||||
|
id="org.eclipse.tm.terminal.local.launch.tabs"
|
||||||
|
description="%terminalLaunchDescription"
|
||||||
|
class="org.eclipse.tm.internal.terminal.local.launch.ui.LocalTerminalLaunchTabGroup"
|
||||||
|
/>
|
||||||
|
</extension>
|
||||||
|
|
||||||
|
</plugin>
|
|
@ -0,0 +1,75 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner 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:
|
||||||
|
* Mirko Raner - [196337] Adapted from org.eclipse.tm.terminal.ssh/ISshSettings
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local;
|
||||||
|
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.ISettingsStore;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interface {@link ILocalTerminalSettings} defines the public interface for connector-specific
|
||||||
|
* settings needed by the {@link LocalTerminalConnector}. The interface is implemented by class
|
||||||
|
* {@link LocalTerminalSettings}.
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.3 $
|
||||||
|
*/
|
||||||
|
public interface ILocalTerminalSettings {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The line separator setting CR (carriage return only; for example, used by Mac OS 9).
|
||||||
|
*/
|
||||||
|
public final static String LINE_SEPARATOR_CR = "\\r"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The line separator setting CRLF (carriage return and line feed; for example, used by
|
||||||
|
* Windows).
|
||||||
|
*/
|
||||||
|
public final static String LINE_SEPARATOR_CRLF = "\\r\\n"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The line separator setting LF (line feed only; used by all UNIX-based systems).
|
||||||
|
*/
|
||||||
|
public final static String LINE_SEPARATOR_LF = "\\n"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the settings from a specified {@link ISettingsStore}.
|
||||||
|
*
|
||||||
|
* TODO: the {@link #load(ISettingsStore)} method should probably extracted to a super-interface
|
||||||
|
* as it appears to be common to all customized settings interfaces
|
||||||
|
*
|
||||||
|
* @param store the {@link ISettingsStore} to load the settings from
|
||||||
|
*/
|
||||||
|
public abstract void load(ISettingsStore store);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the settings to a specified {@link ISettingsStore}.
|
||||||
|
*
|
||||||
|
* TODO: the {@link #save(ISettingsStore)} method should probably extracted to a super-interface
|
||||||
|
* as it appears to be common to all customized settings interfaces
|
||||||
|
*
|
||||||
|
* @param store the {@link ISettingsStore} for storing the settings
|
||||||
|
*/
|
||||||
|
public abstract void save(ISettingsStore store);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the launch configuration that will be started in the terminal.
|
||||||
|
*
|
||||||
|
* @return the launch configuration name
|
||||||
|
*/
|
||||||
|
public abstract String getLaunchConfigurationName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the name of the launch configuration that will be started in the terminal.
|
||||||
|
*
|
||||||
|
* @param configurationName the launch configuration name
|
||||||
|
*/
|
||||||
|
public abstract void setLaunchConfigurationName(String configurationName);
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner 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:
|
||||||
|
* Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local;
|
||||||
|
|
||||||
|
import org.eclipse.jface.resource.ImageDescriptor;
|
||||||
|
import org.eclipse.ui.plugin.AbstractUIPlugin;
|
||||||
|
import org.osgi.framework.BundleContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalActivator} is the bundle activator for the Local Terminal
|
||||||
|
* Connector plug-in.
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.2 $
|
||||||
|
*/
|
||||||
|
public class LocalTerminalActivator extends AbstractUIPlugin {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The plug-in ID of the Local Terminal Connector plug-in.
|
||||||
|
*/
|
||||||
|
public static final String PLUGIN_ID = "org.eclipse.tm.terminal.local"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private static LocalTerminalActivator plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link LocalTerminalActivator}.
|
||||||
|
*/
|
||||||
|
public LocalTerminalActivator() {
|
||||||
|
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the shared plug-in instance.
|
||||||
|
*
|
||||||
|
* @return the shared instance
|
||||||
|
*/
|
||||||
|
public static LocalTerminalActivator getDefault() {
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an image descriptor for the image file at the given plug-in relative path.
|
||||||
|
*
|
||||||
|
* @param path the path to the image
|
||||||
|
* @return the image descriptor
|
||||||
|
*/
|
||||||
|
public static ImageDescriptor getImageDescriptor(String path) {
|
||||||
|
|
||||||
|
return imageDescriptorFromPlugin(PLUGIN_ID, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the bundle and initializes the shared plug-in reference.
|
||||||
|
*
|
||||||
|
* @param context the {@link BundleContext}
|
||||||
|
*
|
||||||
|
* @see AbstractUIPlugin#start(BundleContext)
|
||||||
|
*/
|
||||||
|
public void start(BundleContext context) throws Exception {
|
||||||
|
|
||||||
|
super.start(context);
|
||||||
|
plugin = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the bundle and resets the the shared plug-in reference.
|
||||||
|
*
|
||||||
|
* @param context the {@link BundleContext}
|
||||||
|
*
|
||||||
|
* @see AbstractUIPlugin#stop(BundleContext)
|
||||||
|
*/
|
||||||
|
public void stop(BundleContext context) throws Exception {
|
||||||
|
|
||||||
|
plugin = null;
|
||||||
|
super.stop(context);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,319 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner 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:
|
||||||
|
* Mirko Raner - [196337] initial implementation; some methods adapted from
|
||||||
|
* org.eclipse.tm.terminal.ssh/SshConnector
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local;
|
||||||
|
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.debug.core.DebugEvent;
|
||||||
|
import org.eclipse.debug.core.DebugException;
|
||||||
|
import org.eclipse.debug.core.DebugPlugin;
|
||||||
|
import org.eclipse.debug.core.IDebugEventSetListener;
|
||||||
|
import org.eclipse.debug.core.ILaunch;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
|
||||||
|
import org.eclipse.debug.core.ILaunchManager;
|
||||||
|
import org.eclipse.debug.core.model.IProcess;
|
||||||
|
import org.eclipse.debug.core.model.IStreamMonitor;
|
||||||
|
import org.eclipse.debug.core.model.IStreamsProxy;
|
||||||
|
import org.eclipse.debug.ui.IDebugUIConstants;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.launch.LocalTerminalLaunchUtilities;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.process.LocalTerminalProcessFactory;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.process.LocalTerminalProcessRegistry;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.ISettingsPage;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.ISettingsStore;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.Logger;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.TerminalState;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.provider.TerminalConnectorImpl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalConnector} provides a terminal connector implementation for
|
||||||
|
* connecting to local programs (for example, a locally running <code>bash</code> shell or
|
||||||
|
* <code>vi</code> editor).
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.4 $
|
||||||
|
*/
|
||||||
|
public class LocalTerminalConnector extends TerminalConnectorImpl
|
||||||
|
implements IDebugEventSetListener {
|
||||||
|
|
||||||
|
// Shorthand for attribute names:
|
||||||
|
//
|
||||||
|
private final static String ATTR_CAPTURE_IN_CONSOLE = IDebugUIConstants.ATTR_CAPTURE_IN_CONSOLE;
|
||||||
|
private final static String ATTR_CAPTURE_OUTPUT = DebugPlugin.ATTR_CAPTURE_OUTPUT;
|
||||||
|
private final static String ATTR_PROCESS_FACTORY_ID = DebugPlugin.ATTR_PROCESS_FACTORY_ID;
|
||||||
|
|
||||||
|
private LocalTerminalOutputStream terminalToLocalProcessStream;
|
||||||
|
private LocalTerminalOutputListener outputListener;
|
||||||
|
private LocalTerminalOutputListener errorListener;
|
||||||
|
private ILocalTerminalSettings settings;
|
||||||
|
private IStreamMonitor outputMonitor;
|
||||||
|
private IStreamMonitor errorMonitor;
|
||||||
|
private IProcess process;
|
||||||
|
private ILaunch launch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link LocalTerminalConnector}. This constructor is invoked by the framework.
|
||||||
|
*/
|
||||||
|
public LocalTerminalConnector() {
|
||||||
|
|
||||||
|
settings = new LocalTerminalSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the connector's settings from the specified store.
|
||||||
|
*
|
||||||
|
* @param store the {@link ISettingsStore}
|
||||||
|
*
|
||||||
|
* @see TerminalConnectorImpl#load(ISettingsStore)
|
||||||
|
*
|
||||||
|
* TODO: the load(ISettingsStore) method should probably be made abstract in
|
||||||
|
* TerminalConnectorImpl, otherwise it is not immediately clear that clients need to
|
||||||
|
* override this method if custom settings are necessary (which they usually are).
|
||||||
|
* Maybe the whole settings store mechanism should be redesigned. The current scheme
|
||||||
|
* requires clients to implement load/save methods in their connector implementation
|
||||||
|
* classes (necessity to override is not immediately obvious) and in the settings store
|
||||||
|
* implementations (not enforced at all; merely expected by convention). Structurally,
|
||||||
|
* all client implementations look more or less the same, and probably could be handled
|
||||||
|
* by the framework in a uniform way. Maybe a configuration mechanism using attributes
|
||||||
|
* (like, for example, ILaunchConfiguration) might be beneficial here.
|
||||||
|
*/
|
||||||
|
public void load(ISettingsStore store) {
|
||||||
|
|
||||||
|
settings.load(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the connector's settings into the specified store.
|
||||||
|
* See {@link #load(ISettingsStore)} for additional notes.
|
||||||
|
*
|
||||||
|
* @param store the {@link ISettingsStore}
|
||||||
|
*
|
||||||
|
* @see TerminalConnectorImpl#save(ISettingsStore)
|
||||||
|
*/
|
||||||
|
public void save(ISettingsStore store) {
|
||||||
|
|
||||||
|
settings.save(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the {@link ISettingsPage} for the settings of this connector.
|
||||||
|
*
|
||||||
|
* @return a new page that can be used in a dialog to setup this connection, or
|
||||||
|
* <code>null</code> if the connection cannot be customized or configured
|
||||||
|
*
|
||||||
|
* @see TerminalConnectorImpl#makeSettingsPage()
|
||||||
|
*/
|
||||||
|
public ISettingsPage makeSettingsPage() {
|
||||||
|
|
||||||
|
return new LocalTerminalSettingsPage(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string that represents the settings of the connection.
|
||||||
|
*
|
||||||
|
* @return the name of the launch configuration that is running in the terminal
|
||||||
|
*
|
||||||
|
* @see TerminalConnectorImpl#getSettingsSummary()
|
||||||
|
* @see ILocalTerminalSettings#getLaunchConfigurationName()
|
||||||
|
*/
|
||||||
|
public String getSettingsSummary() {
|
||||||
|
|
||||||
|
return settings.getLaunchConfigurationName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if local echo is required.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the connection settings specify that local echo is enable,
|
||||||
|
* <code>false</code> otherwise
|
||||||
|
*
|
||||||
|
* @see TerminalConnectorImpl#isLocalEcho()
|
||||||
|
* @see LocalTerminalLaunchUtilities#ATTR_LOCAL_ECHO
|
||||||
|
*/
|
||||||
|
public boolean isLocalEcho() {
|
||||||
|
|
||||||
|
return LocalTerminalUtilities.getLocalEcho(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an {@link OutputStream} that writes to the local program's standard input. For the
|
||||||
|
* stream in the other direction (remote to terminal) see
|
||||||
|
* {@link ITerminalControl#getRemoteToTerminalOutputStream()}.
|
||||||
|
*
|
||||||
|
* @return the terminal-to-remote-stream (bytes written to this stream will be sent to the
|
||||||
|
* local program)
|
||||||
|
*/
|
||||||
|
public OutputStream getTerminalToRemoteStream() {
|
||||||
|
|
||||||
|
return terminalToLocalProcessStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connects a locally launched program to the {@link ITerminalControl}.
|
||||||
|
*
|
||||||
|
* @param control the {@link ITerminalControl} through which the user can interact with the
|
||||||
|
* program
|
||||||
|
*/
|
||||||
|
public void connect(ITerminalControl control) {
|
||||||
|
|
||||||
|
super.connect(control);
|
||||||
|
control.setState(TerminalState.CONNECTING);
|
||||||
|
ILaunchConfigurationWorkingCopy workingCopy = null;
|
||||||
|
ILaunchConfiguration configuration = null;
|
||||||
|
try {
|
||||||
|
|
||||||
|
String configurationName = settings.getLaunchConfigurationName();
|
||||||
|
configuration = LocalTerminalUtilities.findLaunchConfiguration(configurationName);
|
||||||
|
|
||||||
|
// Always set the the process factory ID and enable console output (there is no need
|
||||||
|
// to restore these attributes afterwards; disabling console output does not make
|
||||||
|
// sense for terminal launches and will be overridden when the configuration is
|
||||||
|
// actually launched):
|
||||||
|
//
|
||||||
|
workingCopy = configuration.getWorkingCopy();
|
||||||
|
workingCopy.setAttribute(ATTR_CAPTURE_OUTPUT, true);
|
||||||
|
workingCopy.setAttribute(ATTR_CAPTURE_IN_CONSOLE, true);
|
||||||
|
workingCopy.setAttribute(ATTR_PROCESS_FACTORY_ID, LocalTerminalProcessFactory.ID);
|
||||||
|
configuration = workingCopy.doSave();
|
||||||
|
launch = configuration.launch(ILaunchManager.RUN_MODE, null);
|
||||||
|
|
||||||
|
// To prevent a console from being allocated, the launch will actually not contain a
|
||||||
|
// reference to the runtime process. The process has to be obtained from the
|
||||||
|
// LocalTerminalProcessRegistry instead:
|
||||||
|
//
|
||||||
|
process = LocalTerminalProcessRegistry.getFromLaunch(launch);
|
||||||
|
IStreamsProxy streamsProxy = process.getStreamsProxy();
|
||||||
|
|
||||||
|
// Hook up standard input:
|
||||||
|
//
|
||||||
|
terminalToLocalProcessStream = new LocalTerminalOutputStream(process, settings);
|
||||||
|
|
||||||
|
// Hook up standard output:
|
||||||
|
//
|
||||||
|
outputMonitor = streamsProxy.getOutputStreamMonitor();
|
||||||
|
outputListener = new LocalTerminalOutputListener(control, settings);
|
||||||
|
outputMonitor.addListener(outputListener);
|
||||||
|
outputListener.streamAppended(outputMonitor.getContents(), outputMonitor);
|
||||||
|
|
||||||
|
// Hook up standard error:
|
||||||
|
//
|
||||||
|
errorMonitor = streamsProxy.getErrorStreamMonitor();
|
||||||
|
errorListener = new LocalTerminalOutputListener(control, settings);
|
||||||
|
errorMonitor.addListener(errorListener);
|
||||||
|
errorListener.streamAppended(errorMonitor.getContents(), errorMonitor);
|
||||||
|
//
|
||||||
|
// TODO: add proper synchronization for incoming data from stdout and stderr:
|
||||||
|
// currently, the data gets sometimes processed in the wrong order, for example,
|
||||||
|
// the next prompt (which shells like bash print to stderr) sometimes appears
|
||||||
|
// before the command's proper output that was sent to stdout. For example,
|
||||||
|
// you get:
|
||||||
|
//
|
||||||
|
// $ echo hello
|
||||||
|
// $ hello
|
||||||
|
//
|
||||||
|
// instead of the correct output of:
|
||||||
|
//
|
||||||
|
// $ echo hello
|
||||||
|
// hello
|
||||||
|
// $
|
||||||
|
|
||||||
|
// Listen for process termination and update the terminal state:
|
||||||
|
//
|
||||||
|
DebugPlugin.getDefault().addDebugEventListener(this);
|
||||||
|
control.setState(TerminalState.CONNECTED);
|
||||||
|
}
|
||||||
|
catch (CoreException exception) {
|
||||||
|
|
||||||
|
Logger.logException(exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnects the connector if it is currently connected or does nothing otherwise. This method
|
||||||
|
* will try to terminate the underlying launched process and will remove all registered
|
||||||
|
* listeners.
|
||||||
|
*/
|
||||||
|
public void doDisconnect() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
removeAllListeners();
|
||||||
|
|
||||||
|
// To prevent a console from being allocated, Terminal launches don't have an IProcess
|
||||||
|
// associated with them while they are running. However, to properly terminate a launch
|
||||||
|
// the launch has to contain at least one process that can be terminated (launches
|
||||||
|
// without processes effectively cannot be terminated):
|
||||||
|
//
|
||||||
|
LocalTerminalProcessRegistry.addProcessBackToFinishedLaunch(launch);
|
||||||
|
|
||||||
|
// Now, terminate the process if it hasn't been terminated already:
|
||||||
|
//
|
||||||
|
if (launch.canTerminate()) {
|
||||||
|
|
||||||
|
launch.terminate();
|
||||||
|
//
|
||||||
|
// NOTE: canTerminate() merely indicates that the launch has not been terminated
|
||||||
|
// previously already
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (DebugException couldNotTerminate) {
|
||||||
|
|
||||||
|
Logger.logException(couldNotTerminate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listens for self-induced termination of the launched process. For example, this method will
|
||||||
|
* be notified if a launched shell is terminated by pressing Control-D or by calling
|
||||||
|
* <code>exit</code>, or if a <code>vi</code> editor is terminated by means of a
|
||||||
|
* <code>:q!</code> command.
|
||||||
|
*
|
||||||
|
* @param event the debug events
|
||||||
|
*
|
||||||
|
* @see IDebugEventSetListener#handleDebugEvents(DebugEvent[])
|
||||||
|
*/
|
||||||
|
public void handleDebugEvents(DebugEvent[] event) {
|
||||||
|
|
||||||
|
int numberOfEvents = event.length;
|
||||||
|
for (int index = 0; index < numberOfEvents; index++) {
|
||||||
|
|
||||||
|
if (event[index].getSource().equals(process)
|
||||||
|
&& (event[index].getKind() == DebugEvent.TERMINATE)) {
|
||||||
|
|
||||||
|
fControl.setState(TerminalState.CLOSED);
|
||||||
|
removeAllListeners();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes any listeners that the {@link LocalTerminalConnector} might have registered in its
|
||||||
|
* {@link #connect(ITerminalControl)} method. This method is necessary for clean-up when a
|
||||||
|
* connection is closed. It prevents that orphaned or meaningless listeners keep accumulating
|
||||||
|
* on certain objects.
|
||||||
|
*/
|
||||||
|
protected void removeAllListeners() {
|
||||||
|
|
||||||
|
if (outputMonitor != null && outputListener != null) {
|
||||||
|
|
||||||
|
outputMonitor.removeListener(outputListener);
|
||||||
|
}
|
||||||
|
if (errorMonitor != null && errorListener != null) {
|
||||||
|
|
||||||
|
errorMonitor.removeListener(errorListener);
|
||||||
|
}
|
||||||
|
DebugPlugin.getDefault().removeDebugEventListener(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner.
|
||||||
|
* 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:
|
||||||
|
* Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local;
|
||||||
|
|
||||||
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
import org.eclipse.jface.viewers.BaseLabelProvider;
|
||||||
|
import org.eclipse.jface.viewers.ILabelProvider;
|
||||||
|
import org.eclipse.swt.graphics.Image;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.launch.LocalTerminalLaunchUtilities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalLaunchLabelProvider} is an {@link ILabelProvider} for lists (or
|
||||||
|
* tables) of {@link ILaunchConfiguration}s. It returns a configuration's name as the text label,
|
||||||
|
* and the configuration type's regular icon as the image label.
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.2 $
|
||||||
|
*/
|
||||||
|
public class LocalTerminalLaunchLabelProvider extends BaseLabelProvider implements ILabelProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link LocalTerminalLaunchLabelProvider}.
|
||||||
|
*/
|
||||||
|
public LocalTerminalLaunchLabelProvider() {
|
||||||
|
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the image for the label of the given element.
|
||||||
|
*
|
||||||
|
* @param element the element for which the image was requested
|
||||||
|
* @return the image, or <code>null</code> if no image could be found
|
||||||
|
*
|
||||||
|
* @see ILabelProvider#getImage(Object)
|
||||||
|
*/
|
||||||
|
public Image getImage(Object element) {
|
||||||
|
|
||||||
|
if (element instanceof ILaunchConfiguration) {
|
||||||
|
|
||||||
|
return LocalTerminalLaunchUtilities.getImage((ILaunchConfiguration)element);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the text for the label of the given element.
|
||||||
|
*
|
||||||
|
* @param element the element for which to provide the label text
|
||||||
|
* @return the text string used to label the element, or <code>null</code> if there is no text
|
||||||
|
* label for the given object
|
||||||
|
*
|
||||||
|
* @see ILabelProvider#getText(Object)
|
||||||
|
*/
|
||||||
|
public String getText(Object element) {
|
||||||
|
|
||||||
|
if (element instanceof ILaunchConfiguration) {
|
||||||
|
|
||||||
|
return ((ILaunchConfiguration)element).getName();
|
||||||
|
}
|
||||||
|
return String.valueOf(element);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner.
|
||||||
|
* 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:
|
||||||
|
* Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.debug.core.DebugPlugin;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfigurationType;
|
||||||
|
import org.eclipse.debug.core.ILaunchManager;
|
||||||
|
import org.eclipse.jface.viewers.IStructuredContentProvider;
|
||||||
|
import org.eclipse.jface.viewers.Viewer;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalLaunchListProvider} is a {@link IStructuredContentProvider} that
|
||||||
|
* provides a list of all {@link ILaunchConfiguration}s of the type "External Tools"/"Program".
|
||||||
|
* Those launch configurations can be used to start a new session in the Terminal View.
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.1 $
|
||||||
|
*/
|
||||||
|
public class LocalTerminalLaunchListProvider implements IStructuredContentProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link LocalTerminalLaunchListProvider}.
|
||||||
|
*/
|
||||||
|
public LocalTerminalLaunchListProvider() {
|
||||||
|
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the matching {@link ILaunchConfiguration}s for the given input element. This content
|
||||||
|
* provider does not really use the concept of "input" because the input can only be obtained in
|
||||||
|
* one way (from the {@link ILaunchManager}.
|
||||||
|
*
|
||||||
|
* @param input the input element (not checked or used by this method)
|
||||||
|
* @return the matching {@link ILaunchConfiguration}s
|
||||||
|
*
|
||||||
|
* @see IStructuredContentProvider#getElements(Object)
|
||||||
|
*/
|
||||||
|
public Object[] getElements(Object input) {
|
||||||
|
|
||||||
|
ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
|
||||||
|
ILaunchConfigurationType type = LocalTerminalUtilities.PROGRAM_LAUNCH_TYPE;
|
||||||
|
ILaunchConfiguration[] configurations = null;
|
||||||
|
try {
|
||||||
|
|
||||||
|
configurations = launchManager.getLaunchConfigurations(type);
|
||||||
|
}
|
||||||
|
catch (CoreException couldNotObtainLaunchConfigurations) {
|
||||||
|
|
||||||
|
Logger.logException(couldNotObtainLaunchConfigurations);
|
||||||
|
}
|
||||||
|
return configurations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes of this {@link LocalTerminalLaunchListProvider}. Currently, there is no additional
|
||||||
|
* clean-up necessary, and this method is empty.
|
||||||
|
*
|
||||||
|
* @see org.eclipse.jface.viewers.IContentProvider#dispose()
|
||||||
|
*/
|
||||||
|
public void dispose() {
|
||||||
|
|
||||||
|
// Does nothing...
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the {@link LocalTerminalLaunchListProvider} that its input has changed. This method
|
||||||
|
* is currently empty because {@link LocalTerminalLaunchListProvider} is not aware of the
|
||||||
|
* concept of "input"
|
||||||
|
*
|
||||||
|
* @see #getElements(Object)
|
||||||
|
* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(Viewer, Object, Object)
|
||||||
|
*/
|
||||||
|
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
|
||||||
|
|
||||||
|
// Does nothing...
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner.
|
||||||
|
* 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:
|
||||||
|
* Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local;
|
||||||
|
|
||||||
|
import org.eclipse.osgi.util.NLS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalMessages} provides localization keys to internationalized display
|
||||||
|
* messages used by the Local Terminal Connector.
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.3 $
|
||||||
|
*/
|
||||||
|
public class LocalTerminalMessages extends NLS {
|
||||||
|
|
||||||
|
static {
|
||||||
|
|
||||||
|
NLS.initializeMessages(LocalTerminalMessages.class.getName(), LocalTerminalMessages.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocalTerminalMessages() {
|
||||||
|
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The title for the launch configuration selection: "Launch configuration:". */
|
||||||
|
public static String launchConfiguration;
|
||||||
|
|
||||||
|
/** The label for the "New..." button. */
|
||||||
|
public static String labelNew;
|
||||||
|
|
||||||
|
/** The label for the "Edit..." button. */
|
||||||
|
public static String labelEdit;
|
||||||
|
|
||||||
|
/** The label for the "Enable terminal echo" check box. */
|
||||||
|
public static String enableLocalEcho;
|
||||||
|
|
||||||
|
/** The label for the "Send SIGINT when Ctrl-C is pressed" check box. */
|
||||||
|
public static String sendInterruptOnCtrlC;
|
||||||
|
|
||||||
|
/** The line separator option "LF". */
|
||||||
|
public static String lineSeparatorLF;
|
||||||
|
|
||||||
|
/** The line separator option "CR". */
|
||||||
|
public static String lineSeparatorCR;
|
||||||
|
|
||||||
|
/** The line separator option "CRLF". */
|
||||||
|
public static String lineSeparatorCRLF;
|
||||||
|
|
||||||
|
/** The default line separator option. */
|
||||||
|
public static String lineSeparatorDefault;
|
||||||
|
|
||||||
|
/** The base name for new launch configurations. */
|
||||||
|
public static String newTerminalLaunchName;
|
||||||
|
|
||||||
|
/** The error message to be issued if a launch configuration could not be found. */
|
||||||
|
public static String noSuchLaunchConfiguration;
|
||||||
|
|
||||||
|
/** The message displayed while launching a configuration. */
|
||||||
|
public static String launchingConfiguration;
|
||||||
|
|
||||||
|
/** The error message displayed when process creation failed. */
|
||||||
|
public static String couldNotCreateIProcess;
|
||||||
|
|
||||||
|
/** The error message for a missing executable path. */
|
||||||
|
public static String locationNotSpecified;
|
||||||
|
|
||||||
|
/** The error message for a specified but invalid executable path. */
|
||||||
|
public static String invalidLocation;
|
||||||
|
|
||||||
|
/** The error message for an invalid working directory location. */
|
||||||
|
public static String invalidWorkingDirectory;
|
||||||
|
|
||||||
|
/** The title string of the warning displayed when terminal launches are still running. */
|
||||||
|
public static String warningTitleTerminalsStillRunning;
|
||||||
|
|
||||||
|
/** The warning message displayed when terminal launches are still running. */
|
||||||
|
public static String warningMessageTerminalsStillRunning;
|
||||||
|
|
||||||
|
/** The label for the button that quits the workbench anyway. */
|
||||||
|
public static String quitWorkbenchAnyway;
|
||||||
|
|
||||||
|
/** The label for the button that vetoes a shutdown of the workbench. */
|
||||||
|
public static String doNoQuitWorkbench;
|
||||||
|
|
||||||
|
/** The label for a terminal process that was terminated during workbench shut-down. */
|
||||||
|
public static String terminatedProcess;
|
||||||
|
|
||||||
|
/** The name of the launch configuration tab for terminal settings. */
|
||||||
|
public static String terminalTabName;
|
||||||
|
|
||||||
|
/** The group label for the terminal settings on the launch configuration page. */
|
||||||
|
public static String terminalSettings;
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
####################################################################################################
|
||||||
|
# Copyright (c) 2008 Mirko Raner.
|
||||||
|
# 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:
|
||||||
|
# Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
####################################################################################################
|
||||||
|
|
||||||
|
launchConfiguration=Launch configuration\:
|
||||||
|
enableLocalEcho=Enable terminal echo
|
||||||
|
sendInterruptOnCtrlC=Send SIGINT when Ctrl-C is pressed
|
||||||
|
lineSeparatorDefault=Program uses default line separator - or\:
|
||||||
|
lineSeparatorCRLF=CRLF
|
||||||
|
lineSeparatorLF=LF
|
||||||
|
lineSeparatorCR=CR
|
||||||
|
labelNew=New...
|
||||||
|
labelEdit=Edit...
|
||||||
|
terminalTabName=Terminal
|
||||||
|
terminalSettings=Terminal settings\:
|
||||||
|
newTerminalLaunchName=New Terminal Launch
|
||||||
|
noSuchLaunchConfiguration=A launch configuration called ''{0}'' does not exist
|
||||||
|
launchingConfiguration=Launching {0}...
|
||||||
|
couldNotCreateIProcess=The IProcess could not be created
|
||||||
|
locationNotSpecified=Executable location was not specified in configuration ''{0}''
|
||||||
|
invalidLocation=Executable does not exist for the external tool named ''{0}''
|
||||||
|
invalidWorkingDirectory=The path {0} is not a directory and cannot be used as working directory \
|
||||||
|
for ''{1}''
|
||||||
|
warningTitleTerminalsStillRunning=Warning: Terminals with active processes are still running
|
||||||
|
warningMessageTerminalsStillRunning=The workbench is about to be shut down even though one or more \
|
||||||
|
terminals with active processes are still running. You may abort the shut-down of the workbench \
|
||||||
|
or you may quit the workbench nonetheless, in which case processes might be terminated in an \
|
||||||
|
unexpected fashion. You may also terminate processes individually. The workbench shut-down will \
|
||||||
|
continue automatically once no more terminal processes are running.
|
||||||
|
quitWorkbenchAnyway=Quit Workbench Anyway
|
||||||
|
doNoQuitWorkbench=Do Not Quit Workbench
|
||||||
|
terminatedProcess={0} <terminated, exit value: {1}>
|
|
@ -0,0 +1,90 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner.
|
||||||
|
* 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:
|
||||||
|
* Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import org.eclipse.debug.core.IStreamListener;
|
||||||
|
import org.eclipse.debug.core.model.IStreamMonitor;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalOutputListener} is an {@link IStreamListener} that transfers output
|
||||||
|
* from a program's standard output and standard error streams to an {@link ITerminalControl}.
|
||||||
|
* It does so by listening for appended text and sending it to the terminal's
|
||||||
|
* {@link ITerminalControl#getRemoteToTerminalOutputStream()}. The class also performs line
|
||||||
|
* separator conversions as specified by the {@link ILocalTerminalSettings}.
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.2 $
|
||||||
|
*/
|
||||||
|
public class LocalTerminalOutputListener implements IStreamListener {
|
||||||
|
|
||||||
|
private PrintStream printStream;
|
||||||
|
private String lineSeparator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link LocalTerminalOutputListener}.
|
||||||
|
*
|
||||||
|
* @param control the {@link ITerminalControl} to which the received output is forwarded
|
||||||
|
* @param settings the {@link ILocalTerminalSettings}
|
||||||
|
*/
|
||||||
|
public LocalTerminalOutputListener(ITerminalControl control, ILocalTerminalSettings settings) {
|
||||||
|
|
||||||
|
printStream = new PrintStream(control.getRemoteToTerminalOutputStream(), true);
|
||||||
|
lineSeparator = LocalTerminalUtilities.getLineSeparator(settings);
|
||||||
|
if (lineSeparator == null) {
|
||||||
|
|
||||||
|
String defaultLS = System.getProperty(LocalTerminalUtilities.LINE_SEPARATOR_PROPERTY);
|
||||||
|
if (LocalTerminalUtilities.CRLF.equals(defaultLS)) {
|
||||||
|
|
||||||
|
lineSeparator = ILocalTerminalSettings.LINE_SEPARATOR_CRLF;
|
||||||
|
}
|
||||||
|
else if (LocalTerminalUtilities.LF.equals(defaultLS)) {
|
||||||
|
|
||||||
|
lineSeparator = ILocalTerminalSettings.LINE_SEPARATOR_LF;
|
||||||
|
}
|
||||||
|
else if (LocalTerminalUtilities.CR.equals(defaultLS)) {
|
||||||
|
|
||||||
|
lineSeparator = ILocalTerminalSettings.LINE_SEPARATOR_CR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
Logger.log("Unknown default line separator: " + defaultLS); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes new output that was appended to the intercepted stream.
|
||||||
|
*
|
||||||
|
* @param text the new output
|
||||||
|
* @param monitor the {@link IStreamMonitor} from which the output was received (this parameter
|
||||||
|
* is currently not evaluated because each {@link IStreamMonitor} has its own dedicated instance
|
||||||
|
* of {@link LocalTerminalOutputListener} attached)
|
||||||
|
*/
|
||||||
|
public void streamAppended(String text, IStreamMonitor monitor) {
|
||||||
|
|
||||||
|
// The VT100TerminalControl apparently adheres to a strict interpretation of the CR and
|
||||||
|
// LF control codes, i.e., CR moves the caret to the beginning of the line (but does not
|
||||||
|
// move down to the next line), and LF moves down to the next line (but not to the
|
||||||
|
// beginning of the line). Therefore, if the program launched in the terminal does not use
|
||||||
|
// CRLF as its line terminator the line terminators have to be converted to CRLF before
|
||||||
|
// being passed on to the terminal control:
|
||||||
|
//
|
||||||
|
if (!ILocalTerminalSettings.LINE_SEPARATOR_CRLF.equals(lineSeparator)) {
|
||||||
|
|
||||||
|
text = text.replaceAll(lineSeparator, LocalTerminalUtilities.CRLF);
|
||||||
|
}
|
||||||
|
printStream.print(text);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,184 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner.
|
||||||
|
* 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:
|
||||||
|
* Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import org.eclipse.debug.core.model.IProcess;
|
||||||
|
import org.eclipse.debug.core.model.IStreamsProxy;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.process.LocalTerminalProcess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalOutputStream} is an {@link OutputStream} that copies data that is
|
||||||
|
* typed into the terminal to the standard input of the active process. Data that is written to the
|
||||||
|
* stream is directly forwarded to the {@link IStreamsProxy} of the process. CRLF line separators
|
||||||
|
* that are received from the terminal will be automatically converted to the line separator that is
|
||||||
|
* specified in the {@link ILocalTerminalSettings}. The Terminal Control generally sends CR line
|
||||||
|
* separators if the local echo is disabled and CRLF if enabled. The reason for this idiosyncrasy
|
||||||
|
* is not entirely clear right now and the line separator behavior might change in the future.
|
||||||
|
*
|
||||||
|
* TODO: research as to whether the CR/CRLF distinction in VT100TerminalControl.TerminalKeyHandler
|
||||||
|
* (based on the local echo setting) is really necessary
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.4 $
|
||||||
|
*/
|
||||||
|
public class LocalTerminalOutputStream extends OutputStream {
|
||||||
|
|
||||||
|
private final static String NOTHING = ""; //$NON-NLS-1$
|
||||||
|
private final static String CRLF = LocalTerminalUtilities.CRLF;
|
||||||
|
private final static char CR = '\r';
|
||||||
|
private final static char LF = '\n';
|
||||||
|
private final static char CTRL_C = '\03';
|
||||||
|
private final static int TERMINAL_SENDS_CR = 0;
|
||||||
|
private final static int TERMINAL_SENDS_CRLF = 1;
|
||||||
|
private final static int PROGRAM_EXPECTS_LF = 0;
|
||||||
|
private final static int PROGRAM_EXPECTS_CRLF = 1;
|
||||||
|
private final static int PROGRAM_EXPECTS_CR = 2;
|
||||||
|
private final static int NO_CHANGE = 0;
|
||||||
|
private final static int CHANGE_CR_TO_LF = 1;
|
||||||
|
private final static int INSERT_LF_AFTER_CR = 2;
|
||||||
|
private final static int REMOVE_CR = 3;
|
||||||
|
private final static int REMOVE_LF = 4;
|
||||||
|
|
||||||
|
// CRLF conversion table:
|
||||||
|
//
|
||||||
|
// Expected line separator --> | LF | CRLF | CR |
|
||||||
|
// ------------------------------------+-----------------+--------------------+----------------+
|
||||||
|
// Local echo off - control sends CR | change CR to LF | insert LF after CR | no change |
|
||||||
|
// ------------------------------------+-----------------+--------------------+----------------+
|
||||||
|
// Local echo on - control sends CRLF | remove CR | no change | remove LF |
|
||||||
|
//
|
||||||
|
private final static int[][] CRLF_REPLACEMENT = {
|
||||||
|
|
||||||
|
{CHANGE_CR_TO_LF, INSERT_LF_AFTER_CR, NO_CHANGE},
|
||||||
|
{REMOVE_CR, NO_CHANGE, REMOVE_LF}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final boolean sendSIGINTOnCtrlC;
|
||||||
|
private IStreamsProxy streamsProxy;
|
||||||
|
private IProcess process;
|
||||||
|
private int replacement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link LocalTerminalOutputStream}.
|
||||||
|
*
|
||||||
|
* @param process the {@link IProcess} object of the terminal process
|
||||||
|
* @param settings the {@link ILocalTerminalSettings} (currently only used for the line
|
||||||
|
* separator settings)
|
||||||
|
*/
|
||||||
|
public LocalTerminalOutputStream(IProcess process, ILocalTerminalSettings settings) {
|
||||||
|
|
||||||
|
this.process = process;
|
||||||
|
streamsProxy = process.getStreamsProxy();
|
||||||
|
sendSIGINTOnCtrlC = LocalTerminalUtilities.getCtrlC(settings);
|
||||||
|
boolean localEcho = LocalTerminalUtilities.getLocalEcho(settings);
|
||||||
|
int terminalSends = localEcho? TERMINAL_SENDS_CRLF:TERMINAL_SENDS_CR;
|
||||||
|
int programExpects;
|
||||||
|
String lineSeparator = LocalTerminalUtilities.getLineSeparator(settings);
|
||||||
|
if (lineSeparator == null) {
|
||||||
|
|
||||||
|
lineSeparator = System.getProperty(LocalTerminalUtilities.LINE_SEPARATOR_PROPERTY);
|
||||||
|
if (LocalTerminalUtilities.CR.equals(lineSeparator)) {
|
||||||
|
|
||||||
|
programExpects = PROGRAM_EXPECTS_CR;
|
||||||
|
}
|
||||||
|
else if (LocalTerminalUtilities.LF.equals(lineSeparator)) {
|
||||||
|
|
||||||
|
programExpects = PROGRAM_EXPECTS_LF;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
programExpects = PROGRAM_EXPECTS_CRLF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (lineSeparator.equals(ILocalTerminalSettings.LINE_SEPARATOR_LF)) {
|
||||||
|
|
||||||
|
programExpects = PROGRAM_EXPECTS_LF;
|
||||||
|
}
|
||||||
|
else if (lineSeparator.equals(ILocalTerminalSettings.LINE_SEPARATOR_CR)) {
|
||||||
|
|
||||||
|
programExpects = PROGRAM_EXPECTS_CR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
programExpects = PROGRAM_EXPECTS_CRLF;
|
||||||
|
}
|
||||||
|
replacement = CRLF_REPLACEMENT[terminalSends][programExpects];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the specified byte to this output stream.
|
||||||
|
*
|
||||||
|
* @param data the byte
|
||||||
|
* @throws IOException if an I/O error occurs
|
||||||
|
*/
|
||||||
|
public void write(int data) throws IOException {
|
||||||
|
|
||||||
|
write(new byte[] {(byte)data}, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a specified number of bytes from the specified byte array starting at a given offset.
|
||||||
|
*
|
||||||
|
* @param data the array containing the data
|
||||||
|
* @param offset the offset into the array
|
||||||
|
* @param length the number of bytes to be written
|
||||||
|
* @throws IOException of an I/O error occurs
|
||||||
|
*/
|
||||||
|
public void write(byte[] data, int offset, int length) throws IOException {
|
||||||
|
|
||||||
|
String text = new String(data, offset, length);
|
||||||
|
//
|
||||||
|
// TODO: check whether this is correct! new String(byte[], int, int) always uses the default
|
||||||
|
// encoding!
|
||||||
|
|
||||||
|
if (replacement == CHANGE_CR_TO_LF) {
|
||||||
|
|
||||||
|
text = text.replace(CR, LF);
|
||||||
|
}
|
||||||
|
else if (replacement == INSERT_LF_AFTER_CR) {
|
||||||
|
|
||||||
|
text = text.replaceAll(ILocalTerminalSettings.LINE_SEPARATOR_CR, CRLF);
|
||||||
|
}
|
||||||
|
else if (replacement == REMOVE_CR) {
|
||||||
|
|
||||||
|
text = text.replaceAll(ILocalTerminalSettings.LINE_SEPARATOR_CR, NOTHING);
|
||||||
|
}
|
||||||
|
else if (replacement == REMOVE_LF) {
|
||||||
|
|
||||||
|
text = text.replaceAll(ILocalTerminalSettings.LINE_SEPARATOR_LF, NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process Ctrl-C in the proper order:
|
||||||
|
//
|
||||||
|
int positionOfCtrlC = -1;
|
||||||
|
while (sendSIGINTOnCtrlC && (positionOfCtrlC = text.indexOf(CTRL_C)) != -1) {
|
||||||
|
|
||||||
|
// Send text up to (and including) the Ctrl-C to the process, then send a SIGINT:
|
||||||
|
//
|
||||||
|
streamsProxy.write(text.substring(0, positionOfCtrlC+1));
|
||||||
|
if (process instanceof LocalTerminalProcess) {
|
||||||
|
|
||||||
|
((LocalTerminalProcess)process).interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the part of the text that was already sent:
|
||||||
|
//
|
||||||
|
text = text.substring(positionOfCtrlC+1);
|
||||||
|
}
|
||||||
|
if (text.length() > 0) {
|
||||||
|
|
||||||
|
streamsProxy.write(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner 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:
|
||||||
|
* Mirko Raner - [196337] Adapted from org.eclipse.tm.terminal.ssh/SshSettings
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.ISettingsStore;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalSettings} is the default implementation of the
|
||||||
|
* {@link ILocalTerminalSettings} interface.
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.3 $
|
||||||
|
*/
|
||||||
|
public class LocalTerminalSettings implements ILocalTerminalSettings {
|
||||||
|
|
||||||
|
private String launchConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the settings from the given {@link ISettingsStore}.
|
||||||
|
* This method loads the store contents by means of reflection. This is clearly overkill for
|
||||||
|
* the few settings supported by this class, but the code is much more reusable. Pretty much
|
||||||
|
* every implementation of a custom settings store is implemented in the same fashion and
|
||||||
|
* might be replace by a single centralized implementation.
|
||||||
|
*
|
||||||
|
* TODO: check for possibilities to reuse this code!
|
||||||
|
*
|
||||||
|
* @param store the {@link ISettingsStore}
|
||||||
|
* @see ILocalTerminalSettings#load(ISettingsStore)
|
||||||
|
*/
|
||||||
|
public void load(ISettingsStore store) {
|
||||||
|
|
||||||
|
Field[] declaredField = getClass().getDeclaredFields();
|
||||||
|
int numberOfFields = declaredField.length;
|
||||||
|
for (int index = 0; index < numberOfFields; index++) {
|
||||||
|
|
||||||
|
Field field = declaredField[index];
|
||||||
|
Class type = field.getType();
|
||||||
|
Object value = store.get(field.getName());
|
||||||
|
if (type.equals(boolean.class)) {
|
||||||
|
|
||||||
|
value = Boolean.valueOf((String)value);
|
||||||
|
}
|
||||||
|
// TODO: further conversions need to be added as new settings types are introduced
|
||||||
|
try {
|
||||||
|
|
||||||
|
field.set(this, value);
|
||||||
|
}
|
||||||
|
catch (IllegalAccessException illegalAccess) {
|
||||||
|
|
||||||
|
Logger.logException(illegalAccess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the settings to the specified {@link ISettingsStore}.
|
||||||
|
* See {@link #load(ISettingsStore)} for further implementation notes.
|
||||||
|
*
|
||||||
|
* @param store the {@link ISettingsStore}
|
||||||
|
*
|
||||||
|
* @see ILocalTerminalSettings#save(ISettingsStore)
|
||||||
|
*/
|
||||||
|
public void save(ISettingsStore store) {
|
||||||
|
|
||||||
|
Field[] declaredField = getClass().getDeclaredFields();
|
||||||
|
int numberOfFields = declaredField.length;
|
||||||
|
for (int index = 0; index < numberOfFields; index++) {
|
||||||
|
|
||||||
|
Field field = declaredField[index];
|
||||||
|
try {
|
||||||
|
|
||||||
|
field.setAccessible(true);
|
||||||
|
store.put(field.getName(), String.valueOf(field.get(this)));
|
||||||
|
}
|
||||||
|
catch (IllegalAccessException illegalAccess) {
|
||||||
|
|
||||||
|
Logger.logException(illegalAccess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ILocalTerminalSettings#getLaunchConfigurationName()
|
||||||
|
*/
|
||||||
|
public String getLaunchConfigurationName() {
|
||||||
|
|
||||||
|
return launchConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ILocalTerminalSettings#setLaunchConfigurationName(String)
|
||||||
|
*/
|
||||||
|
public void setLaunchConfigurationName(String launchConfiguration) {
|
||||||
|
|
||||||
|
this.launchConfiguration = launchConfiguration;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,287 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner.
|
||||||
|
* 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:
|
||||||
|
* Mirko Raner - [196337] Adapted from org.eclipse.tm.terminal.ssh/SshSettingsPage
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.debug.core.DebugPlugin;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfigurationType;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
|
||||||
|
import org.eclipse.debug.core.ILaunchManager;
|
||||||
|
import org.eclipse.debug.internal.ui.DebugUIPlugin;
|
||||||
|
import org.eclipse.debug.ui.DebugUITools;
|
||||||
|
import org.eclipse.debug.ui.ILaunchGroup;
|
||||||
|
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.TableViewer;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
|
import org.eclipse.swt.events.SelectionListener;
|
||||||
|
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.Label;
|
||||||
|
import org.eclipse.swt.widgets.Layout;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
import org.eclipse.swt.widgets.Table;
|
||||||
|
import org.eclipse.swt.widgets.Widget;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.ui.DependentHeightComposite;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.ISettingsPage;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalSettingsPage} is an implementation {@link ISettingsPage} for
|
||||||
|
* local program connections.
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.4 $
|
||||||
|
*/
|
||||||
|
public class LocalTerminalSettingsPage
|
||||||
|
implements ISettingsPage, ISelectionChangedListener, SelectionListener {
|
||||||
|
|
||||||
|
private ILocalTerminalSettings settings;
|
||||||
|
private TableViewer viewer;
|
||||||
|
private Button buttonEdit;
|
||||||
|
private Button buttonNew;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link LocalTerminalSettingsPage} that reflects the settings of the specified
|
||||||
|
* {@link ILocalTerminalSettings} object.
|
||||||
|
*
|
||||||
|
* @param settings the {@link ILocalTerminalSettings}
|
||||||
|
*/
|
||||||
|
public LocalTerminalSettingsPage(ILocalTerminalSettings settings) {
|
||||||
|
|
||||||
|
this.settings = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the {@link org.eclipse.swt.widgets.Control} for the settings page.
|
||||||
|
* (NOTE: contrary to the common pattern, this method does not actually return the Control it
|
||||||
|
* created)
|
||||||
|
*
|
||||||
|
* @param parent the parent {@link Composite} into which the control is to be inserted
|
||||||
|
*
|
||||||
|
* @see ISettingsPage#createControl(Composite)
|
||||||
|
*/
|
||||||
|
public void createControl(Composite parent) {
|
||||||
|
|
||||||
|
Composite enclosing = parent.getParent();
|
||||||
|
Layout enclosingLayout = enclosing.getLayout();
|
||||||
|
int extra = 0;
|
||||||
|
if (enclosingLayout instanceof GridLayout) {
|
||||||
|
|
||||||
|
extra = -2*((GridLayout)enclosingLayout).marginHeight-2;
|
||||||
|
}
|
||||||
|
Composite composite = new DependentHeightComposite(parent, SWT.NONE, enclosing, extra);
|
||||||
|
//
|
||||||
|
// TODO: This is a HACK that ensures proper resizing of the settings page inside the
|
||||||
|
// StackLayout of the PageBook. The following code makes implicit assumptions about
|
||||||
|
// the internal layout of surrounding widgets. This is something that should be
|
||||||
|
// properly addressed in the framework (maybe in the PageBook class).
|
||||||
|
|
||||||
|
GridLayout layout = new GridLayout();
|
||||||
|
layout.marginWidth = layout.marginHeight = 0;
|
||||||
|
layout.horizontalSpacing = layout.verticalSpacing = 0;
|
||||||
|
composite.setLayout(layout);
|
||||||
|
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
|
||||||
|
Label label = new Label(composite, SWT.NONE);
|
||||||
|
label.setText(LocalTerminalMessages.launchConfiguration);
|
||||||
|
label.setLayoutData(new GridData());
|
||||||
|
|
||||||
|
// Create list of available launch configurations:
|
||||||
|
//
|
||||||
|
Composite tableAndButtons = new Composite(composite, SWT.NONE);
|
||||||
|
tableAndButtons.setLayoutData(new GridData(GridData.FILL_BOTH));
|
||||||
|
layout = new GridLayout(2, false);
|
||||||
|
layout.marginWidth = 0;
|
||||||
|
tableAndButtons.setLayout(layout);
|
||||||
|
Table table = new Table(tableAndButtons, SWT.BORDER);
|
||||||
|
viewer = new TableViewer(table);
|
||||||
|
viewer.setLabelProvider(new LocalTerminalLaunchLabelProvider());
|
||||||
|
viewer.setContentProvider(new LocalTerminalLaunchListProvider());
|
||||||
|
viewer.setInput(new Object());
|
||||||
|
viewer.addSelectionChangedListener(this);
|
||||||
|
table.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 0, 2));
|
||||||
|
buttonNew = pushButton(tableAndButtons, LocalTerminalMessages.labelNew, false);
|
||||||
|
buttonEdit = pushButton(tableAndButtons, LocalTerminalMessages.labelEdit, true);
|
||||||
|
buttonEdit.setEnabled(settings.getLaunchConfigurationName() != null);
|
||||||
|
//
|
||||||
|
// NOTE: echo and line separator settings were moved to the launch configuration!
|
||||||
|
|
||||||
|
// NOTE: loadSettings() is actually NOT called by the framework but needs to be called
|
||||||
|
// by the settings page itself
|
||||||
|
// TODO: this should be fixed in the framework; otherwise there is really no point
|
||||||
|
// in having it be a part of the ISettingsPage interface
|
||||||
|
//
|
||||||
|
loadSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the settings from the internal {@link ILocalTerminalSettings} object.
|
||||||
|
* This method will update the UI to reflect the current settings.
|
||||||
|
*
|
||||||
|
* @see ISettingsPage#loadSettings()
|
||||||
|
*/
|
||||||
|
public void loadSettings() {
|
||||||
|
|
||||||
|
String configurationName = settings.getLaunchConfigurationName();
|
||||||
|
ILaunchConfiguration configuration;
|
||||||
|
try {
|
||||||
|
|
||||||
|
configuration = LocalTerminalUtilities.findLaunchConfiguration(configurationName);
|
||||||
|
}
|
||||||
|
catch (CoreException couldNotFindLaunchConfiguration) {
|
||||||
|
|
||||||
|
configuration = null;
|
||||||
|
}
|
||||||
|
if (settings.getLaunchConfigurationName() != null && configuration != null) {
|
||||||
|
|
||||||
|
viewer.setSelection(new StructuredSelection(configuration), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the settings that are currently displayed in the UI to the internal
|
||||||
|
* {@link ILocalTerminalSettings} object.
|
||||||
|
*
|
||||||
|
* @see ISettingsPage#saveSettings()
|
||||||
|
*/
|
||||||
|
public void saveSettings() {
|
||||||
|
|
||||||
|
if (viewer != null && !viewer.getSelection().isEmpty()) {
|
||||||
|
|
||||||
|
IStructuredSelection selection = (IStructuredSelection)viewer.getSelection();
|
||||||
|
Object element = selection.getFirstElement();
|
||||||
|
if (element instanceof ILaunchConfiguration) {
|
||||||
|
|
||||||
|
String launchConfiguration = ((ILaunchConfiguration)element).getName();
|
||||||
|
settings.setLaunchConfigurationName(launchConfiguration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the current settings are valid for starting a terminal session.
|
||||||
|
* This method will only return <code>true</code> if a launch configuration is selected.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if a launch configuration has been selected, <code>false</code>
|
||||||
|
* otherwise
|
||||||
|
*/
|
||||||
|
public boolean validateSettings() {
|
||||||
|
|
||||||
|
return viewer != null && !viewer.getSelection().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disables the Edit... button depending on whether a launch configuration is
|
||||||
|
* currently selected in the viewer.
|
||||||
|
*
|
||||||
|
* @see ISelectionChangedListener#selectionChanged(SelectionChangedEvent)
|
||||||
|
*/
|
||||||
|
public void selectionChanged(SelectionChangedEvent event) {
|
||||||
|
|
||||||
|
buttonEdit.setEnabled(!event.getSelection().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles default button clicks for the Edit... and New.. buttons. This method will simply
|
||||||
|
* pass on the call to {@link #widgetSelected(SelectionEvent)}.
|
||||||
|
*
|
||||||
|
* @param event the {@link SelectionEvent}
|
||||||
|
*
|
||||||
|
* @see SelectionListener#widgetDefaultSelected(SelectionEvent)
|
||||||
|
*/
|
||||||
|
public void widgetDefaultSelected(SelectionEvent event) {
|
||||||
|
|
||||||
|
widgetSelected(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles default button clicks for the Edit... and New.. buttons.
|
||||||
|
*
|
||||||
|
* @param event the {@link SelectionEvent}
|
||||||
|
*
|
||||||
|
* @see SelectionListener#widgetSelected(SelectionEvent)
|
||||||
|
*/
|
||||||
|
public void widgetSelected(SelectionEvent event) {
|
||||||
|
|
||||||
|
ILaunchConfiguration configuration = null;
|
||||||
|
Widget widget = event.widget;
|
||||||
|
if (widget == null) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (widget.equals(buttonNew)) {
|
||||||
|
|
||||||
|
ILaunchConfigurationWorkingCopy newlyCreatedConfiguration;
|
||||||
|
ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
|
||||||
|
String baseName = LocalTerminalMessages.newTerminalLaunchName;
|
||||||
|
String uniqueName = launchManager.generateUniqueLaunchConfigurationNameFrom(baseName);
|
||||||
|
ILaunchConfigurationType type = LocalTerminalUtilities.PROGRAM_LAUNCH_TYPE;
|
||||||
|
try {
|
||||||
|
|
||||||
|
newlyCreatedConfiguration = type.newInstance(null, uniqueName);
|
||||||
|
configuration = newlyCreatedConfiguration.doSave();
|
||||||
|
}
|
||||||
|
catch (CoreException couldNotCreateNewLaunchConfiguration) {
|
||||||
|
|
||||||
|
Logger.logException(couldNotCreateNewLaunchConfiguration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (widget.equals(buttonEdit) || configuration != null) {
|
||||||
|
|
||||||
|
ILaunchGroup group;
|
||||||
|
Shell shell = DebugUIPlugin.getShell();
|
||||||
|
IStructuredSelection selection = (IStructuredSelection)viewer.getSelection();
|
||||||
|
if (configuration == null) {
|
||||||
|
|
||||||
|
configuration = (ILaunchConfiguration)selection.getFirstElement();
|
||||||
|
}
|
||||||
|
group = DebugUITools.getLaunchGroup(configuration, ILaunchManager.RUN_MODE);
|
||||||
|
String groupID = group.getIdentifier();
|
||||||
|
DebugUITools.openLaunchConfigurationDialog(shell, configuration, groupID, null);
|
||||||
|
//
|
||||||
|
// TODO: handle return value (maybe start terminal right away if "Run" was selected)
|
||||||
|
// - a return value of Window.CANCEL indicates that "Close" was selected
|
||||||
|
// - a return value of Window.OK indicates that "Run" was selected
|
||||||
|
// TODO: prevent "Run" button from launching in the regular console
|
||||||
|
// (maybe tweak process factory settings before opening the configuration in the
|
||||||
|
// dialog?)
|
||||||
|
|
||||||
|
viewer.refresh();
|
||||||
|
viewer.setSelection(new StructuredSelection(configuration), true);
|
||||||
|
//
|
||||||
|
// TODO: handle renamed configurations; setSelection(...) will not work if the user
|
||||||
|
// renamed the configuration in the dialog (apparently, because renaming actually
|
||||||
|
// creates a different ILaunchConfiguration object, rather than just renaming the
|
||||||
|
// existing one)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------ PRIVATE SECTION ---------------------------------------//
|
||||||
|
|
||||||
|
private Button pushButton(Composite parent, String label, boolean grabVertical) {
|
||||||
|
|
||||||
|
GridData layoutData;
|
||||||
|
Button button = new Button(parent, SWT.PUSH);
|
||||||
|
button.setText(label);
|
||||||
|
layoutData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING|GridData.HORIZONTAL_ALIGN_FILL);
|
||||||
|
layoutData.grabExcessVerticalSpace = grabVertical;
|
||||||
|
button.setLayoutData(layoutData);
|
||||||
|
button.addSelectionListener(this);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,158 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner.
|
||||||
|
* 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:
|
||||||
|
* Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.debug.core.DebugPlugin;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfigurationType;
|
||||||
|
import org.eclipse.debug.core.ILaunchManager;
|
||||||
|
import org.eclipse.osgi.util.NLS;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.launch.LocalTerminalLaunchDelegate;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.launch.LocalTerminalLaunchUtilities;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalUtilities} is a collection of commonly used constants and utility
|
||||||
|
* methods.
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.3 $
|
||||||
|
*/
|
||||||
|
public class LocalTerminalUtilities {
|
||||||
|
|
||||||
|
private static String NULL = null;
|
||||||
|
private static String LOCAL_TERMINAL = LocalTerminalLaunchDelegate.LAUNCH_CONFIGURATION_TYPE_ID;
|
||||||
|
|
||||||
|
/** The name of the line separator system property (i.e., "<code>line.separator</code>"). */
|
||||||
|
public final static String LINE_SEPARATOR_PROPERTY = "line.separator"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/** The line separator CRLF (i.e., "<code>\r\n</code>"). */
|
||||||
|
public final static String CRLF = "\r\n"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/** The line separator CR (i.e., "<code>\r</code>"). */
|
||||||
|
public final static String CR = "\r"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/** The line separator LF (i.e., "<code>\n</code>"). */
|
||||||
|
public final static String LF = "\n"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private LocalTerminalUtilities() {
|
||||||
|
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The {@link DebugPlugin}'s {@link ILaunchManager} instance. */
|
||||||
|
public final static ILaunchManager LAUNCH_MANAGER = DebugPlugin.getDefault().getLaunchManager();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link ILaunchConfigurationType} for "Program" launches (in the "External Tools"
|
||||||
|
* category).
|
||||||
|
*/
|
||||||
|
public final static ILaunchConfigurationType PROGRAM_LAUNCH_TYPE =
|
||||||
|
LAUNCH_MANAGER.getLaunchConfigurationType(LOCAL_TERMINAL);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a launch configuration by its name.
|
||||||
|
*
|
||||||
|
* @param name the name of the launch configuration
|
||||||
|
* @return the corresponding {@link ILaunchConfiguration} object or <code>null</code> if the
|
||||||
|
* configuration could not be found
|
||||||
|
* @throws CoreException if there was a general problem accessing launch configurations
|
||||||
|
*/
|
||||||
|
public static ILaunchConfiguration findLaunchConfiguration(String name) throws CoreException {
|
||||||
|
|
||||||
|
ILaunchConfiguration[] configuration;
|
||||||
|
ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
|
||||||
|
configuration = manager.getLaunchConfigurations(LocalTerminalUtilities.PROGRAM_LAUNCH_TYPE);
|
||||||
|
int numberOfConfigurations = configuration.length;
|
||||||
|
for (int index = 0; index < numberOfConfigurations; index++) {
|
||||||
|
|
||||||
|
if (configuration[index].getName().equals(name)) {
|
||||||
|
|
||||||
|
return configuration[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String error = NLS.bind(LocalTerminalMessages.noSuchLaunchConfiguration, name);
|
||||||
|
throw new CoreException(new Status(IStatus.ERROR, LocalTerminalActivator.PLUGIN_ID, error));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the local echo setting that is stored in the launch configuration for the given
|
||||||
|
* {@link ILocalTerminalSettings}.
|
||||||
|
*
|
||||||
|
* @param settings the {@link ILocalTerminalSettings}
|
||||||
|
* @return <code>true</code> for local echo enabled, <code>false</code> otherwise
|
||||||
|
*/
|
||||||
|
public static boolean getLocalEcho(ILocalTerminalSettings settings) {
|
||||||
|
|
||||||
|
return getBooleanSetting(settings, LocalTerminalLaunchUtilities.ATTR_LOCAL_ECHO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Ctrl-C/SIGINT setting that is stored in the launch configuration for the given
|
||||||
|
* {@link ILocalTerminalSettings}.
|
||||||
|
*
|
||||||
|
* @param settings the {@link ILocalTerminalSettings}
|
||||||
|
* @return <code>true</code> if sending SIGINT for Ctrl-C is enabled,
|
||||||
|
* <code>false</code> otherwise
|
||||||
|
*/
|
||||||
|
public static boolean getCtrlC(ILocalTerminalSettings settings) {
|
||||||
|
|
||||||
|
return getBooleanSetting(settings, LocalTerminalLaunchUtilities.ATTR_CTRL_C);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the line separator setting that is stored in the launch configuration for the given
|
||||||
|
* {@link ILocalTerminalSettings}.
|
||||||
|
*
|
||||||
|
* @param settings the {@link ILocalTerminalSettings}
|
||||||
|
* @return {@link ILocalTerminalSettings#LINE_SEPARATOR_LF},
|
||||||
|
* {@link ILocalTerminalSettings#LINE_SEPARATOR_CRLF},
|
||||||
|
* {@link ILocalTerminalSettings#LINE_SEPARATOR_CR}, or <code>null</code> for the platform's
|
||||||
|
* default line separator
|
||||||
|
*/
|
||||||
|
public static String getLineSeparator(ILocalTerminalSettings settings) {
|
||||||
|
|
||||||
|
String configurationName = settings.getLaunchConfigurationName();
|
||||||
|
try {
|
||||||
|
|
||||||
|
String ls;
|
||||||
|
ILaunchConfiguration configuration = findLaunchConfiguration(configurationName);
|
||||||
|
ls = configuration.getAttribute(LocalTerminalLaunchUtilities.ATTR_LINE_SEPARATOR, NULL);
|
||||||
|
return ls;
|
||||||
|
}
|
||||||
|
catch (CoreException exception) {
|
||||||
|
|
||||||
|
Logger.logException(exception);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------- PRIVATE SECTION --------------------------------------//
|
||||||
|
|
||||||
|
private static boolean getBooleanSetting(ILocalTerminalSettings settings, String attribute) {
|
||||||
|
|
||||||
|
String configurationName = settings.getLaunchConfigurationName();
|
||||||
|
try {
|
||||||
|
|
||||||
|
ILaunchConfiguration configuration = findLaunchConfiguration(configurationName);
|
||||||
|
return configuration.getAttribute(attribute, false);
|
||||||
|
}
|
||||||
|
catch (CoreException exception) {
|
||||||
|
|
||||||
|
Logger.logException(exception);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,265 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner 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:
|
||||||
|
* Mirko Raner - [196337] Adapted from org.eclipse.ui.externaltools/ProgramLaunchDelegate
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local.launch;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.eclipse.cdt.utils.pty.PTY;
|
||||||
|
import org.eclipse.cdt.utils.spawner.ProcessFactory;
|
||||||
|
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.Status;
|
||||||
|
import org.eclipse.debug.core.DebugPlugin;
|
||||||
|
import org.eclipse.debug.core.ILaunch;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
import org.eclipse.debug.core.model.IProcess;
|
||||||
|
import org.eclipse.debug.core.model.LaunchConfigurationDelegate;
|
||||||
|
import org.eclipse.debug.ui.CommonTab;
|
||||||
|
import org.eclipse.osgi.util.NLS;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.LocalTerminalActivator;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.LocalTerminalMessages;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.LocalTerminalUtilities;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.Logger;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalLaunchDelegate} provides a launch configuration delegate for local
|
||||||
|
* terminal launches. It is based on the <code>ProgramLaunchDelegate</code> class in the
|
||||||
|
* <code>org.eclipse.ui.externaltools</code> plug-in. In contrast to the original class,
|
||||||
|
* {@link LocalTerminalLaunchDelegate} creates its low-level {@link Process} object using the CDT
|
||||||
|
* {@link ProcessFactory}, which allows the process to run with a pseudo-terminal ({@link PTY}).
|
||||||
|
*
|
||||||
|
* @author Mirko Raner and others
|
||||||
|
* @version $Revision: 1.2 $
|
||||||
|
*/
|
||||||
|
public class LocalTerminalLaunchDelegate extends LaunchConfigurationDelegate {
|
||||||
|
|
||||||
|
private final static String EMPTY = ""; //$NON-NLS-1$
|
||||||
|
private final static String PLUGIN_ID = LocalTerminalActivator.PLUGIN_ID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The launch configuration type ID for terminal launches.
|
||||||
|
*/
|
||||||
|
public final static String LAUNCH_CONFIGURATION_TYPE_ID = PLUGIN_ID + ".launch"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private static LocalTerminalStillRunningListener workbenchCloseListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link LocalTerminalLaunchDelegate}.
|
||||||
|
*/
|
||||||
|
public LocalTerminalLaunchDelegate() {
|
||||||
|
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launches a new Local Terminal configuration in the specified mode. The launch object has
|
||||||
|
* already been registered with the launch manager.
|
||||||
|
*
|
||||||
|
* @param configuration the {@link ILaunchConfiguration} to launch
|
||||||
|
* @param mode the mode in which to launch; currently, Local Terminal launches only support the
|
||||||
|
* mode {@link org.eclipse.debug.core.ILaunchManager#RUN_MODE}
|
||||||
|
* @param progressMonitor an {@link IProgressMonitor}, or <code>null</code> for no progress
|
||||||
|
* monitoring
|
||||||
|
* @param launch the {@link ILaunch} object
|
||||||
|
* @exception CoreException if launching fails
|
||||||
|
*/
|
||||||
|
public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch,
|
||||||
|
IProgressMonitor progressMonitor) throws CoreException {
|
||||||
|
|
||||||
|
// Extract all relevant information from the ILaunchConfiguration; the original
|
||||||
|
// ProgramLaunchDelegate class checks for cancellation again and again after each step,
|
||||||
|
// which is a somewhat suspect pattern; however, for now, LocalTerminalLaunchDelegate
|
||||||
|
// handles cancellation in the same way:
|
||||||
|
//
|
||||||
|
if (progressMonitor.isCanceled()) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
IPath location = LocalTerminalLaunchUtilities.getLocation(configuration);
|
||||||
|
if (progressMonitor.isCanceled()) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
IPath workingDirectory = LocalTerminalLaunchUtilities.getWorkingDirectory(configuration);
|
||||||
|
if (progressMonitor.isCanceled()) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String[] arguments = LocalTerminalLaunchUtilities.getArguments(configuration);
|
||||||
|
if (progressMonitor.isCanceled()) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String[] commandLine = new String[arguments != null? arguments.length+1:1];
|
||||||
|
commandLine[0] = location.toOSString();
|
||||||
|
if (arguments != null) {
|
||||||
|
|
||||||
|
System.arraycopy(arguments, 0, commandLine, 1, arguments.length);
|
||||||
|
}
|
||||||
|
File workingDirectoryAsFile = null;
|
||||||
|
if (workingDirectory != null) {
|
||||||
|
|
||||||
|
workingDirectoryAsFile = workingDirectory.toFile();
|
||||||
|
}
|
||||||
|
if (progressMonitor.isCanceled()) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String[] environment = LocalTerminalUtilities.LAUNCH_MANAGER.getEnvironment(configuration);
|
||||||
|
if (progressMonitor.isCanceled()) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// TODO: check if there is a better way of handling cancellation of terminal launches!
|
||||||
|
|
||||||
|
// Install an IWindowListener that checks for left-over terminal processes when the
|
||||||
|
// workbench is closed:
|
||||||
|
//
|
||||||
|
if (workbenchCloseListener == null) {
|
||||||
|
|
||||||
|
workbenchCloseListener = new LocalTerminalStillRunningListener();
|
||||||
|
PlatformUI.getWorkbench().addWorkbenchListener(workbenchCloseListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the low-level Process object:
|
||||||
|
//
|
||||||
|
Process spawner;
|
||||||
|
try {
|
||||||
|
|
||||||
|
ProcessFactory factory = ProcessFactory.getFactory();
|
||||||
|
if (PTY.isSupported()) {
|
||||||
|
|
||||||
|
spawner = factory.exec(commandLine, environment, workingDirectoryAsFile, new PTY());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
spawner = factory.exec(commandLine, environment, workingDirectoryAsFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException exception) {
|
||||||
|
|
||||||
|
Status error;
|
||||||
|
String message = exception.getMessage();
|
||||||
|
error = new Status(IStatus.ERROR, LocalTerminalActivator.PLUGIN_ID, message, exception);
|
||||||
|
throw new CoreException(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use program name as "process type" attribute:
|
||||||
|
//
|
||||||
|
Map processAttributes = new HashMap();
|
||||||
|
String programName = location.lastSegment();
|
||||||
|
String extension = location.getFileExtension();
|
||||||
|
if (extension != null) {
|
||||||
|
|
||||||
|
programName = programName.substring(0, programName.length()-extension.length()-1);
|
||||||
|
}
|
||||||
|
processAttributes.put(IProcess.ATTR_PROCESS_TYPE, programName.toLowerCase());
|
||||||
|
|
||||||
|
// Create the IProcess:
|
||||||
|
//
|
||||||
|
IProcess process = null;
|
||||||
|
if (spawner != null) {
|
||||||
|
|
||||||
|
String[] configurationName = {configuration.getName()};
|
||||||
|
String task = NLS.bind(LocalTerminalMessages.launchingConfiguration, configurationName);
|
||||||
|
progressMonitor.beginTask(task, IProgressMonitor.UNKNOWN);
|
||||||
|
process = DebugPlugin.newProcess(launch, spawner, commandLine[0], processAttributes);
|
||||||
|
}
|
||||||
|
if (spawner == null || process == null) {
|
||||||
|
|
||||||
|
if (spawner != null) {
|
||||||
|
|
||||||
|
spawner.destroy();
|
||||||
|
}
|
||||||
|
String pluginID = LocalTerminalActivator.PLUGIN_ID;
|
||||||
|
String errorMessage = LocalTerminalMessages.couldNotCreateIProcess;
|
||||||
|
Status error = new Status(IStatus.ERROR, pluginID, IStatus.ERROR, errorMessage, null);
|
||||||
|
throw new CoreException(error);
|
||||||
|
}
|
||||||
|
process.setAttribute(IProcess.ATTR_CMDLINE, generateCommandLine(commandLine));
|
||||||
|
|
||||||
|
// Wait for process termination if necessary (though probably highly unusual for terminal
|
||||||
|
// launches); again, the busy waiting pattern was copied from ProgramLaunchDelegate and is
|
||||||
|
// somewhat suspect:
|
||||||
|
//
|
||||||
|
if (!CommonTab.isLaunchInBackground(configuration)) {
|
||||||
|
|
||||||
|
while (!process.isTerminated()) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (progressMonitor.isCanceled()) {
|
||||||
|
|
||||||
|
process.terminate();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Thread.sleep(50);
|
||||||
|
}
|
||||||
|
catch (InterruptedException interrupt) {
|
||||||
|
|
||||||
|
Logger.logException(interrupt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// TODO: find a better replacement for the busy waiting loop
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------- PRIVATE SECTION --------------------------------------//
|
||||||
|
|
||||||
|
private String generateCommandLine(String[] commandLine) {
|
||||||
|
|
||||||
|
if (commandLine.length < 1) {
|
||||||
|
|
||||||
|
return EMPTY;
|
||||||
|
}
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
for (int element = 0; element < commandLine.length; element++) {
|
||||||
|
|
||||||
|
if (element > 0) {
|
||||||
|
|
||||||
|
buffer.append(' ');
|
||||||
|
}
|
||||||
|
StringBuffer argument = new StringBuffer();
|
||||||
|
char[] characters = commandLine[element].toCharArray();
|
||||||
|
boolean argumentContainsSpace = false;
|
||||||
|
for (int index = 0; index < characters.length; index++) {
|
||||||
|
|
||||||
|
char character = characters[index];
|
||||||
|
if (character == '"') {
|
||||||
|
|
||||||
|
argument.append('\\');
|
||||||
|
}
|
||||||
|
else if (character == ' ') {
|
||||||
|
|
||||||
|
argumentContainsSpace = true;
|
||||||
|
}
|
||||||
|
argument.append(character);
|
||||||
|
}
|
||||||
|
if (argumentContainsSpace) {
|
||||||
|
|
||||||
|
buffer.append('"').append(argument).append('"');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
buffer.append(argument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,201 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner 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:
|
||||||
|
* Mirko Raner - [196337] Adapted from org.eclipse.ui.externaltools/ExternalToolsUtil
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local.launch;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Path;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.core.variables.IStringVariableManager;
|
||||||
|
import org.eclipse.core.variables.VariablesPlugin;
|
||||||
|
import org.eclipse.debug.core.DebugPlugin;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
import org.eclipse.debug.ui.DebugUITools;
|
||||||
|
import org.eclipse.osgi.util.NLS;
|
||||||
|
import org.eclipse.swt.graphics.Image;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.LocalTerminalActivator;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.LocalTerminalMessages;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalLaunchUtilities} provides some utility methods that are used by the
|
||||||
|
* {@link LocalTerminalLaunchDelegate}. The class is based on the <code>ExternalToolsUtil</code>
|
||||||
|
* class in the <code>org.eclipse.ui.externaltools</code> plug-in. This code had to be duplicated
|
||||||
|
* because the original class is not part of the public API of its plug-in.
|
||||||
|
*
|
||||||
|
* @author Mirko Raner and others
|
||||||
|
* @version $Revision: 1.2 $
|
||||||
|
*/
|
||||||
|
public class LocalTerminalLaunchUtilities {
|
||||||
|
|
||||||
|
/** The launch configuration attribute for the local echo setting. */
|
||||||
|
public final static String ATTR_LOCAL_ECHO = LocalTerminalActivator.PLUGIN_ID +
|
||||||
|
".echo"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/** The launch configuration attribute for the Ctrl-C/SIGINT setting. */
|
||||||
|
public final static String ATTR_CTRL_C = LocalTerminalActivator.PLUGIN_ID +
|
||||||
|
".sigint"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/** The launch configuration attribute for the line terminator setting. */
|
||||||
|
public final static String ATTR_LINE_SEPARATOR = LocalTerminalActivator.PLUGIN_ID +
|
||||||
|
".lineseparator"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private final static String[] EMPTY = {};
|
||||||
|
private final static String STRING = null;
|
||||||
|
|
||||||
|
// These constants were copied from IExternalToolConstants to avoid references to internal API:
|
||||||
|
//
|
||||||
|
private final static String XT = "org.eclipse.ui.externaltools"; //$NON-NLS-1$;
|
||||||
|
private final static String ATTR_LOCATION = XT+".ATTR_LOCATION"; //$NON-NLS-1$
|
||||||
|
private final static String ATTR_TOOL_ARGUMENTS = XT+".ATTR_TOOL_ARGUMENTS"; //$NON-NLS-1$
|
||||||
|
private final static String ATTR_WORKING_DIRECTORY = XT+".ATTR_WORKING_DIRECTORY"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private LocalTerminalLaunchUtilities() {
|
||||||
|
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the image that should be used for representing the given launch configuration.
|
||||||
|
*
|
||||||
|
* @param configuration the {@link ILaunchConfiguration}
|
||||||
|
* @return an SWT {@link Image} or <code>null</code> if no suitable image was found
|
||||||
|
*/
|
||||||
|
public static Image getImage(ILaunchConfiguration configuration) {
|
||||||
|
|
||||||
|
String identifier;
|
||||||
|
try {
|
||||||
|
|
||||||
|
identifier = configuration.getType().getIdentifier();
|
||||||
|
}
|
||||||
|
catch (CoreException couldNotDetermineConfigurationType) {
|
||||||
|
|
||||||
|
identifier = null;
|
||||||
|
Logger.logException(couldNotDetermineConfigurationType);
|
||||||
|
}
|
||||||
|
if (identifier != null) {
|
||||||
|
|
||||||
|
return DebugUITools.getImage(identifier);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expands and returns the location attribute of the given launch configuration. The location is
|
||||||
|
* verified to point to an existing file in the local file system.
|
||||||
|
*
|
||||||
|
* @param configuration the {@link ILaunchConfiguration}
|
||||||
|
* @return an absolute path to a file in the local file system
|
||||||
|
* @throws CoreException if unable to retrieve the associated launch configuration attribute, or
|
||||||
|
* if unable to resolve any variables, or if the resolved location does not point to an existing
|
||||||
|
* file in the local file system
|
||||||
|
*/
|
||||||
|
public static IPath getLocation(ILaunchConfiguration configuration) throws CoreException {
|
||||||
|
|
||||||
|
Object[] configurationName = {configuration.getName()};
|
||||||
|
String location = configuration.getAttribute(ATTR_LOCATION, STRING);
|
||||||
|
if (location == null) {
|
||||||
|
|
||||||
|
abort(NLS.bind(LocalTerminalMessages.locationNotSpecified, configurationName), null, 0);
|
||||||
|
}
|
||||||
|
String expandedLocation = getStringVariableManager().performStringSubstitution(location);
|
||||||
|
if (expandedLocation == null || expandedLocation.length() == 0) {
|
||||||
|
|
||||||
|
abort(NLS.bind(LocalTerminalMessages.invalidLocation, configurationName), null, 0);
|
||||||
|
}
|
||||||
|
File file = new File(expandedLocation);
|
||||||
|
if (!file.isFile()) {
|
||||||
|
|
||||||
|
abort(NLS.bind(LocalTerminalMessages.invalidLocation, configurationName), null, 0);
|
||||||
|
}
|
||||||
|
return new Path(expandedLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expands and returns the working directory attribute of the given launch configuration.
|
||||||
|
* Returns <code>null</code> if a working directory is not specified. If specified, the working
|
||||||
|
* directory is guaranteed to point to an existing directory in the local file system.
|
||||||
|
*
|
||||||
|
* @param configuration the {@link ILaunchConfiguration}
|
||||||
|
* @return an absolute path to a directory in the local file system, or <code>null</code> if
|
||||||
|
* no working directory was specified
|
||||||
|
* @throws CoreException if unable to retrieve the associated launch configuration attribute,
|
||||||
|
* or if unable to resolve any variables, or if the resolved location does not point to an
|
||||||
|
* existing directory in the local file system
|
||||||
|
*/
|
||||||
|
public static IPath getWorkingDirectory(ILaunchConfiguration configuration)
|
||||||
|
throws CoreException {
|
||||||
|
|
||||||
|
String location = configuration.getAttribute(ATTR_WORKING_DIRECTORY, STRING);
|
||||||
|
if (location != null) {
|
||||||
|
|
||||||
|
String expandedLocation;
|
||||||
|
expandedLocation = getStringVariableManager().performStringSubstitution(location);
|
||||||
|
if (expandedLocation.length() > 0) {
|
||||||
|
|
||||||
|
File path = new File(expandedLocation);
|
||||||
|
if (!path.isDirectory()) {
|
||||||
|
|
||||||
|
Object[] detail = {expandedLocation, configuration.getName()};
|
||||||
|
abort(NLS.bind(LocalTerminalMessages.invalidWorkingDirectory, detail), null, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Path(expandedLocation);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expands and returns the arguments attribute of the given launch configuration. Returns
|
||||||
|
* <code>null</code> if arguments were not specified.
|
||||||
|
*
|
||||||
|
* @param configuration the {@link ILaunchConfiguration}
|
||||||
|
* @return an array of resolved arguments, or <code>null</code> if no arguments were specified
|
||||||
|
* @throws CoreException if unable to retrieve the associated launch configuration attribute,
|
||||||
|
* or if unable to resolve any variables
|
||||||
|
*/
|
||||||
|
public static String[] getArguments(ILaunchConfiguration configuration) throws CoreException {
|
||||||
|
|
||||||
|
String arguments = configuration.getAttribute(ATTR_TOOL_ARGUMENTS, STRING);
|
||||||
|
if (arguments != null) {
|
||||||
|
|
||||||
|
String expanded = getStringVariableManager().performStringSubstitution(arguments);
|
||||||
|
return parseStringIntoList(expanded);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------- PRIVATE SECTION --------------------------------------//
|
||||||
|
|
||||||
|
private static IStringVariableManager getStringVariableManager() {
|
||||||
|
|
||||||
|
return VariablesPlugin.getDefault().getStringVariableManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] parseStringIntoList(String arguments) {
|
||||||
|
|
||||||
|
if (arguments == null || arguments.length() == 0) {
|
||||||
|
|
||||||
|
return EMPTY;
|
||||||
|
}
|
||||||
|
return DebugPlugin.parseArguments(arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void abort(String text, Throwable exception, int code) throws CoreException {
|
||||||
|
|
||||||
|
Status status;
|
||||||
|
status = new Status(IStatus.ERROR, LocalTerminalActivator.PLUGIN_ID, code, text, exception);
|
||||||
|
throw new CoreException(status);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner 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:
|
||||||
|
* Mirko Raner - [196337] Adapted from org.eclipse.ui.externaltools/ProgramLaunchDelegate
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local.launch;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.debug.core.ILaunch;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfigurationType;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.LocalTerminalUtilities;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.launch.ui.LocalTerminalStillRunningDialog;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.Logger;
|
||||||
|
import org.eclipse.ui.IWorkbench;
|
||||||
|
import org.eclipse.ui.IWorkbenchListener;
|
||||||
|
import org.eclipse.ui.IWorkbenchWindow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalStillRunningListener} is an {@link IWorkbenchListener} that warns
|
||||||
|
* the user about any terminal launches that are still running when the workbench closes. The user
|
||||||
|
* might want to take specific action to deal with such left-over processes. Typically, this
|
||||||
|
* listener will trigger only on very rare cases because the
|
||||||
|
* {@link org.eclipse.tm.internal.terminal.provisional.api.ITerminalConnector} implementation will
|
||||||
|
* terminate left-over launches when the workbench window is closed. However, it is possible that
|
||||||
|
* a terminal launch does not get automatically terminated, for example, if it was started through
|
||||||
|
* an External Tools launch rather than through the terminal.
|
||||||
|
*
|
||||||
|
* The class {@link LocalTerminalStillRunningListener} is inspired by the
|
||||||
|
* <code>ProgramLaunchWindowListener</code> class inside <code>ProgramLaunchDelegate</code> in the
|
||||||
|
* <code>org.eclipse.ui.externaltools</code> plug-in, though it works through a slightly different
|
||||||
|
* mechanism.
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.1 $
|
||||||
|
*/
|
||||||
|
public class LocalTerminalStillRunningListener implements IWorkbenchListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link LocalTerminalStillRunningListener}.
|
||||||
|
*/
|
||||||
|
public LocalTerminalStillRunningListener() {
|
||||||
|
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets notified when the workbench is closed and informs the user about any left-over
|
||||||
|
* terminal launches.
|
||||||
|
*
|
||||||
|
* @param workbench the {@link IWorkbench}
|
||||||
|
* @param forced <code>true</code> if a forced shutdown occurred, <code>false</code> otherwise
|
||||||
|
* @return <code>true</code> to allow the workbench to proceed with shutdown, <code>false</code>
|
||||||
|
* to prevent a shutdown (only for non-forced shutdown)
|
||||||
|
*/
|
||||||
|
public boolean preShutdown(IWorkbench workbench, boolean forced) {
|
||||||
|
|
||||||
|
if (forced) {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ILaunchConfigurationType launchType;
|
||||||
|
String launchTypeID = LocalTerminalLaunchDelegate.LAUNCH_CONFIGURATION_TYPE_ID;
|
||||||
|
launchType = LocalTerminalUtilities.LAUNCH_MANAGER.getLaunchConfigurationType(launchTypeID);
|
||||||
|
if (launchType == null) {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
List notTerminated = new ArrayList();
|
||||||
|
ILaunch launches[] = LocalTerminalUtilities.LAUNCH_MANAGER.getLaunches();
|
||||||
|
ILaunchConfigurationType configurationType;
|
||||||
|
ILaunchConfiguration configuration;
|
||||||
|
for (int launch = 0; launch < launches.length; launch++) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
configuration = launches[launch].getLaunchConfiguration();
|
||||||
|
if (configuration == null) {
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
configurationType= configuration.getType();
|
||||||
|
}
|
||||||
|
catch (CoreException exception) {
|
||||||
|
|
||||||
|
Logger.logException(exception);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (configurationType.equals(launchType) && !launches[launch].isTerminated()) {
|
||||||
|
|
||||||
|
notTerminated.add(launches[launch]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!notTerminated.isEmpty()) {
|
||||||
|
|
||||||
|
IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
|
||||||
|
ILaunch[] launch = (ILaunch[])notTerminated.toArray(new ILaunch[notTerminated.size()]);
|
||||||
|
return LocalTerminalStillRunningDialog.openDialog(window.getShell(), launch);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <i>Not implemented</i>.
|
||||||
|
* @see IWorkbenchListener#postShutdown(IWorkbench)
|
||||||
|
*/
|
||||||
|
public void postShutdown(IWorkbench workbench) {
|
||||||
|
|
||||||
|
// Not implemented
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner.
|
||||||
|
* 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:
|
||||||
|
* Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local.launch.ui;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IConfigurationElement;
|
||||||
|
import org.eclipse.core.runtime.IExtensionRegistry;
|
||||||
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
|
||||||
|
import org.eclipse.debug.ui.CommonTab;
|
||||||
|
import org.eclipse.debug.ui.EnvironmentTab;
|
||||||
|
import org.eclipse.debug.ui.IDebugUIConstants;
|
||||||
|
import org.eclipse.debug.ui.ILaunchConfigurationDialog;
|
||||||
|
import org.eclipse.debug.ui.ILaunchConfigurationTab;
|
||||||
|
import org.eclipse.debug.ui.ILaunchConfigurationTabGroup;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalLaunchTabGroup} defines the tabs for the launch configuration
|
||||||
|
* dialog that is used for terminal-based launches. The tab groups consists of the main tab for
|
||||||
|
* a standard program launch (lifted from the <code>org.eclipse.ui.externaltools</code> plug-in), the
|
||||||
|
* custom {@link LocalTerminalSettingsTab}, and the {@link EnvironmentTab} and {@link CommonTab},
|
||||||
|
* which can be publicly accessed from the <code>org.eclipse.debug.ui</code> plug-in.
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.1 $
|
||||||
|
**/
|
||||||
|
public class LocalTerminalLaunchTabGroup extends AbstractLaunchConfigurationTabGroup
|
||||||
|
implements IDebugUIConstants {
|
||||||
|
|
||||||
|
private final static String ID = "id"; //$NON-NLS-1$
|
||||||
|
private final static String CLASS = "class"; //$NON-NLS-1$
|
||||||
|
private final static String LC_TAB_GROUPS = EXTENSION_POINT_LAUNCH_CONFIGURATION_TAB_GROUPS;
|
||||||
|
private final static String PROGRAM_TAB_GROUP =
|
||||||
|
"org.eclipse.ui.externaltools.launchConfigurationTabGroup.program"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link LocalTerminalLaunchTabGroup}.
|
||||||
|
**/
|
||||||
|
public LocalTerminalLaunchTabGroup() {
|
||||||
|
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the tabs contained in the local terminal launch configuration dialog for the specified
|
||||||
|
* launch mode. The tabs control's are not yet created. This is the first method called in the
|
||||||
|
* life-cycle of a tab group.
|
||||||
|
*
|
||||||
|
* @param dialog the launch configuration dialog this tab group is contained in
|
||||||
|
* @param mode the mode the launch configuration dialog was opened in
|
||||||
|
* @see AbstractLaunchConfigurationTabGroup#createTabs(ILaunchConfigurationDialog, String)
|
||||||
|
**/
|
||||||
|
public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
|
||||||
|
|
||||||
|
ILaunchConfigurationTab main = getMainTab(dialog, mode);
|
||||||
|
ILaunchConfigurationTab terminal = new LocalTerminalSettingsTab();
|
||||||
|
ILaunchConfigurationTab environment = new EnvironmentTab();
|
||||||
|
ILaunchConfigurationTab common = new CommonTab();
|
||||||
|
ILaunchConfigurationTab[] tabs = {main, terminal, environment, common};
|
||||||
|
setTabs(tabs);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------- PRIVATE SECTION -------------------------------------//
|
||||||
|
|
||||||
|
private ILaunchConfigurationTab getMainTab(ILaunchConfigurationDialog dialog, String mode) {
|
||||||
|
|
||||||
|
// Find the main tab for the external program launch in the registry (a direct search is
|
||||||
|
// only possible for extensions that actually declare a unique ID, which most extensions
|
||||||
|
// don't; the search for the "id" attribute of a configuration element has to be done
|
||||||
|
// manually):
|
||||||
|
//
|
||||||
|
IConfigurationElement[] element;
|
||||||
|
IExtensionRegistry registry = Platform.getExtensionRegistry();
|
||||||
|
element = registry.getConfigurationElementsFor(IDebugUIConstants.PLUGIN_ID, LC_TAB_GROUPS);
|
||||||
|
int numberOfElements = element.length;
|
||||||
|
for (int index = 0; index < numberOfElements; index++) {
|
||||||
|
|
||||||
|
if (element[index].getAttribute(ID).equals(PROGRAM_TAB_GROUP)) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
ILaunchConfigurationTabGroup tabGroup;
|
||||||
|
Object executable = element[index].createExecutableExtension(CLASS);
|
||||||
|
tabGroup = (ILaunchConfigurationTabGroup)executable;
|
||||||
|
tabGroup.createTabs(dialog, mode);
|
||||||
|
|
||||||
|
// It's not possible to make assumptions about the class name of the program
|
||||||
|
// main tab (without over-stepping API boundaries), but it's usually the very
|
||||||
|
// first tab in the group (which is an assumption that actually also over-steps
|
||||||
|
// API boundaries, but it's the best possible solution, short of copying the
|
||||||
|
// whole source code):
|
||||||
|
//
|
||||||
|
return tabGroup.getTabs()[0];
|
||||||
|
}
|
||||||
|
catch (CoreException exception) {
|
||||||
|
|
||||||
|
Logger.logException(exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,265 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner.
|
||||||
|
* 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:
|
||||||
|
* Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local.launch.ui;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
|
||||||
|
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
|
||||||
|
import org.eclipse.debug.ui.DebugUITools;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
|
import org.eclipse.swt.events.SelectionListener;
|
||||||
|
import org.eclipse.swt.graphics.Image;
|
||||||
|
import org.eclipse.swt.layout.GridData;
|
||||||
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
|
import org.eclipse.swt.layout.RowLayout;
|
||||||
|
import org.eclipse.swt.widgets.Button;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Group;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.ILocalTerminalSettings;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.LocalTerminalMessages;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.launch.LocalTerminalLaunchDelegate;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.launch.LocalTerminalLaunchUtilities;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalSettingsTab} provides the UI for custom settings that are specific
|
||||||
|
* to terminal-based launches. Currently, the tab allows the user to control the local echo settings
|
||||||
|
* and the line separator string.
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.2 $
|
||||||
|
**/
|
||||||
|
public class LocalTerminalSettingsTab extends AbstractLaunchConfigurationTab
|
||||||
|
implements SelectionListener {
|
||||||
|
|
||||||
|
private final static String NULL = null;
|
||||||
|
|
||||||
|
private Button buttonEcho;
|
||||||
|
private Button buttonCtrlC;
|
||||||
|
private Button separatorDefault;
|
||||||
|
private Button separatorLF;
|
||||||
|
private Button separatorCRLF;
|
||||||
|
private Button separatorCR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link LocalTerminalSettingsTab}.
|
||||||
|
**/
|
||||||
|
public LocalTerminalSettingsTab() {
|
||||||
|
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the top-level control for this launch configuration tab under the given parent
|
||||||
|
* composite. This method is called once on tab creation.
|
||||||
|
*
|
||||||
|
* @param parent the parent {@link Composite}
|
||||||
|
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(Composite)
|
||||||
|
**/
|
||||||
|
public void createControl(Composite parent) {
|
||||||
|
|
||||||
|
Composite container = new Composite(parent, SWT.NONE);
|
||||||
|
setControl(container);
|
||||||
|
container.setLayout(new GridLayout());
|
||||||
|
Group composite = new Group(container, SWT.NONE);
|
||||||
|
composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||||
|
composite.setText(LocalTerminalMessages.terminalSettings);
|
||||||
|
composite.setLayout(new GridLayout());
|
||||||
|
|
||||||
|
// Create echo check box:
|
||||||
|
//
|
||||||
|
buttonEcho = button(composite, LocalTerminalMessages.enableLocalEcho, SWT.CHECK);
|
||||||
|
buttonEcho.setLayoutData(new GridData());
|
||||||
|
|
||||||
|
// Create Ctrl-C/SIGINT check box:
|
||||||
|
//
|
||||||
|
buttonCtrlC = button(composite, LocalTerminalMessages.sendInterruptOnCtrlC, SWT.CHECK);
|
||||||
|
buttonCtrlC.setLayoutData(new GridData());
|
||||||
|
|
||||||
|
// Create radio buttons for line separator settings:
|
||||||
|
//
|
||||||
|
Composite separator = new Composite(composite, SWT.NONE);
|
||||||
|
RowLayout rowLayout = new RowLayout();
|
||||||
|
rowLayout.wrap = false;
|
||||||
|
separator.setLayout(rowLayout);
|
||||||
|
separatorDefault = button(separator, LocalTerminalMessages.lineSeparatorDefault, SWT.RADIO);
|
||||||
|
separatorLF = button(separator, LocalTerminalMessages.lineSeparatorLF, SWT.RADIO);
|
||||||
|
separatorCRLF = button(separator, LocalTerminalMessages.lineSeparatorCRLF, SWT.RADIO);
|
||||||
|
separatorCR = button(separator, LocalTerminalMessages.lineSeparatorCR, SWT.RADIO);
|
||||||
|
separator.setLayoutData(new GridData());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of this tab.
|
||||||
|
*
|
||||||
|
* @return the name of this tab
|
||||||
|
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
|
||||||
|
**/
|
||||||
|
public String getName() {
|
||||||
|
|
||||||
|
return LocalTerminalMessages.terminalTabName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the image for this tab, or <code>null</code> if none
|
||||||
|
*
|
||||||
|
* @return the image for this tab, or <code>null</code> if none
|
||||||
|
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#getImage()
|
||||||
|
**/
|
||||||
|
public Image getImage() {
|
||||||
|
|
||||||
|
return DebugUITools.getImage(LocalTerminalLaunchDelegate.LAUNCH_CONFIGURATION_TYPE_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes this tab's controls with values from the given launch configuration. This method
|
||||||
|
* is called when a configuration is selected to view or edit, after the tab's control has been
|
||||||
|
* created.
|
||||||
|
*
|
||||||
|
* @param configuration the launch configuration
|
||||||
|
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(ILaunchConfiguration)
|
||||||
|
**/
|
||||||
|
public void initializeFrom(ILaunchConfiguration configuration) {
|
||||||
|
|
||||||
|
boolean echo;
|
||||||
|
try {
|
||||||
|
|
||||||
|
echo = configuration.getAttribute(LocalTerminalLaunchUtilities.ATTR_LOCAL_ECHO, false);
|
||||||
|
}
|
||||||
|
catch (CoreException exception) {
|
||||||
|
|
||||||
|
Logger.logException(exception);
|
||||||
|
echo = false;
|
||||||
|
}
|
||||||
|
boolean ctrlC;
|
||||||
|
try {
|
||||||
|
|
||||||
|
ctrlC = configuration.getAttribute(LocalTerminalLaunchUtilities.ATTR_CTRL_C, false);
|
||||||
|
}
|
||||||
|
catch (CoreException exception) {
|
||||||
|
|
||||||
|
Logger.logException(exception);
|
||||||
|
ctrlC = false;
|
||||||
|
}
|
||||||
|
String ls;
|
||||||
|
try {
|
||||||
|
|
||||||
|
ls = configuration.getAttribute(LocalTerminalLaunchUtilities.ATTR_LINE_SEPARATOR, NULL);
|
||||||
|
}
|
||||||
|
catch (CoreException exception) {
|
||||||
|
|
||||||
|
Logger.logException(exception);
|
||||||
|
ls = null;
|
||||||
|
}
|
||||||
|
buttonEcho.setSelection(echo);
|
||||||
|
buttonCtrlC.setSelection(ctrlC);
|
||||||
|
if (ILocalTerminalSettings.LINE_SEPARATOR_LF.equals(ls)) {
|
||||||
|
|
||||||
|
separatorLF.setSelection(true);
|
||||||
|
}
|
||||||
|
else if (ILocalTerminalSettings.LINE_SEPARATOR_LF.equals(ls)) {
|
||||||
|
|
||||||
|
separatorLF.setSelection(true);
|
||||||
|
}
|
||||||
|
else if (ILocalTerminalSettings.LINE_SEPARATOR_CRLF.equals(ls)) {
|
||||||
|
|
||||||
|
separatorCRLF.setSelection(true);
|
||||||
|
}
|
||||||
|
else if (ILocalTerminalSettings.LINE_SEPARATOR_CR.equals(ls)) {
|
||||||
|
|
||||||
|
separatorCR.setSelection(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
separatorDefault.setSelection(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies values from this tab into the given launch configuration.
|
||||||
|
*
|
||||||
|
* @param configuration the launch configuration
|
||||||
|
* @see AbstractLaunchConfigurationTab#performApply(ILaunchConfigurationWorkingCopy)
|
||||||
|
**/
|
||||||
|
public void performApply(ILaunchConfigurationWorkingCopy configuration) {
|
||||||
|
|
||||||
|
boolean echo = buttonEcho.getSelection();
|
||||||
|
configuration.setAttribute(LocalTerminalLaunchUtilities.ATTR_LOCAL_ECHO, echo);
|
||||||
|
boolean ctrlC = buttonCtrlC.getSelection();
|
||||||
|
configuration.setAttribute(LocalTerminalLaunchUtilities.ATTR_CTRL_C, ctrlC);
|
||||||
|
String lineSeparator = null;
|
||||||
|
if (separatorCRLF.getSelection()) {
|
||||||
|
|
||||||
|
lineSeparator = ILocalTerminalSettings.LINE_SEPARATOR_CRLF;
|
||||||
|
}
|
||||||
|
else if (separatorCR.getSelection()) {
|
||||||
|
|
||||||
|
lineSeparator = ILocalTerminalSettings.LINE_SEPARATOR_CR;
|
||||||
|
}
|
||||||
|
else if (separatorLF.getSelection()) {
|
||||||
|
|
||||||
|
lineSeparator = ILocalTerminalSettings.LINE_SEPARATOR_LF;
|
||||||
|
}
|
||||||
|
configuration.setAttribute(LocalTerminalLaunchUtilities.ATTR_LINE_SEPARATOR, lineSeparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the given launch configuration with default values for this tab. This method is
|
||||||
|
* called when a new launch configuration is created such that the configuration can be
|
||||||
|
* initialized with meaningful values. This method may be called before the tab's control is
|
||||||
|
* created.
|
||||||
|
*
|
||||||
|
* @param configuration the launch configuration
|
||||||
|
* @see AbstractLaunchConfigurationTab#setDefaults(ILaunchConfigurationWorkingCopy)
|
||||||
|
**/
|
||||||
|
public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
|
||||||
|
|
||||||
|
configuration.setAttribute(LocalTerminalLaunchUtilities.ATTR_LOCAL_ECHO, false);
|
||||||
|
configuration.setAttribute(LocalTerminalLaunchUtilities.ATTR_CTRL_C, false);
|
||||||
|
configuration.setAttribute(LocalTerminalLaunchUtilities.ATTR_LINE_SEPARATOR, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles selection of any of the buttons in the tab.
|
||||||
|
*
|
||||||
|
* @param event the {@link SelectionEvent}
|
||||||
|
* @see SelectionListener#widgetSelected(SelectionEvent)
|
||||||
|
**/
|
||||||
|
public void widgetSelected(SelectionEvent event) {
|
||||||
|
|
||||||
|
setDirty(true);
|
||||||
|
getLaunchConfigurationDialog().updateButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles default selection of any of the buttons in the tab.
|
||||||
|
*
|
||||||
|
* @param event the {@link SelectionEvent}
|
||||||
|
* @see SelectionListener#widgetDefaultSelected(SelectionEvent)
|
||||||
|
**/
|
||||||
|
public void widgetDefaultSelected(SelectionEvent event) {
|
||||||
|
|
||||||
|
widgetSelected(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------- PRIVATE SECTION -------------------------------------//
|
||||||
|
|
||||||
|
private Button button(Composite parent, String label, int buttonType) {
|
||||||
|
|
||||||
|
Button button = new Button(parent, buttonType);
|
||||||
|
button.addSelectionListener(this);
|
||||||
|
button.setText(label);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,298 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner.
|
||||||
|
* 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:
|
||||||
|
* Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local.launch.ui;
|
||||||
|
|
||||||
|
import org.eclipse.debug.core.DebugException;
|
||||||
|
import org.eclipse.debug.core.ILaunch;
|
||||||
|
import org.eclipse.debug.core.ILaunchesListener2;
|
||||||
|
import org.eclipse.debug.ui.DebugUITools;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.eclipse.osgi.util.NLS;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.custom.ScrolledComposite;
|
||||||
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
|
import org.eclipse.swt.events.SelectionListener;
|
||||||
|
import org.eclipse.swt.graphics.Color;
|
||||||
|
import org.eclipse.swt.graphics.Image;
|
||||||
|
import org.eclipse.swt.graphics.RGB;
|
||||||
|
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.ToolBar;
|
||||||
|
import org.eclipse.swt.widgets.ToolItem;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.LocalTerminalMessages;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.LocalTerminalUtilities;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.launch.LocalTerminalLaunchUtilities;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.process.LocalTerminalProcessRegistry;
|
||||||
|
import org.eclipse.tm.internal.terminal.provisional.api.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalStillRunningDialog} is a dialog that is shown when the workbench is
|
||||||
|
* about to exit and one or more terminal launches are still running. It gives the user a choice
|
||||||
|
* between aborting the workbench shut-down, proceeding, or terminating the outstanding launches
|
||||||
|
* individually. When no more launches are running the dialog will automatically disappear and
|
||||||
|
* workbench shut-down will proceed.
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.1 $
|
||||||
|
*/
|
||||||
|
public class LocalTerminalStillRunningDialog extends MessageDialog
|
||||||
|
implements Runnable, SelectionListener, ILaunchesListener2 {
|
||||||
|
|
||||||
|
private final static String TITLE = LocalTerminalMessages.warningTitleTerminalsStillRunning;
|
||||||
|
private final static String MESSAGE = LocalTerminalMessages.warningMessageTerminalsStillRunning;
|
||||||
|
private final static String QUIT_ANYWAY = LocalTerminalMessages.quitWorkbenchAnyway;
|
||||||
|
private final static String DO_NOT_QUIT = LocalTerminalMessages.doNoQuitWorkbench;
|
||||||
|
private final static String[] BUTTONS = {QUIT_ANYWAY, DO_NOT_QUIT};
|
||||||
|
private final static RGB WHITE = new RGB(255, 255, 255);
|
||||||
|
private final static int SCROLLABLE_HEIGHT = 100;
|
||||||
|
|
||||||
|
// Image key copied from IInternalDebugUIConstants:
|
||||||
|
//
|
||||||
|
private final static String IMG_LCL_TERMINATE = "IMG_LCL_TERMINATE"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private ILaunch[] unterminated;
|
||||||
|
private Composite content;
|
||||||
|
|
||||||
|
private LocalTerminalStillRunningDialog(Shell parentShell, ILaunch[] launches) {
|
||||||
|
|
||||||
|
super(parentShell, TITLE, null, MESSAGE, WARNING, BUTTONS, 0);
|
||||||
|
setShellStyle(SWT.BORDER|SWT.TITLE|SWT.APPLICATION_MODAL|SWT.RESIZE|SWT.MAX);
|
||||||
|
unterminated = launches;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a dialog that lists all terminal launches that have not yet terminated.
|
||||||
|
*
|
||||||
|
* @param shell the parent {@link Shell} for the dialog
|
||||||
|
* @param launches the launches that have not yet terminated
|
||||||
|
* @return <code>true</code> to allow the workbench to proceed with shutdown, <code>false</code>
|
||||||
|
* to prevent a shutdown (only for non-forced shutdown)
|
||||||
|
*/
|
||||||
|
public static boolean openDialog(Shell shell, ILaunch[] launches) {
|
||||||
|
|
||||||
|
LocalTerminalStillRunningDialog dialog;
|
||||||
|
dialog = new LocalTerminalStillRunningDialog(shell, launches);
|
||||||
|
dialog.setBlockOnOpen(true);
|
||||||
|
try {
|
||||||
|
|
||||||
|
LocalTerminalUtilities.LAUNCH_MANAGER.addLaunchListener(dialog);
|
||||||
|
return dialog.open() == 0;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
|
||||||
|
LocalTerminalUtilities.LAUNCH_MANAGER.removeLaunchListener(dialog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the dialog buttons and sets the focus on the default button. This is done because
|
||||||
|
* otherwise the focus might land on one of the stop buttons of the unterminated launches, which
|
||||||
|
* looks somewhat funny.
|
||||||
|
*
|
||||||
|
* @param parent the parent {@link Composite}
|
||||||
|
*/
|
||||||
|
protected void createButtonsForButtonBar(Composite parent) {
|
||||||
|
|
||||||
|
super.createButtonsForButtonBar(parent);
|
||||||
|
getButton(1).forceFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the custom area of the dialog that shows the list of terminal launches that have not
|
||||||
|
* yet been terminated.
|
||||||
|
*
|
||||||
|
* @param parent the parent {@link Composite} into which the custom area is inserted
|
||||||
|
* @return the {@link ScrolledComposite} for the custom area
|
||||||
|
*
|
||||||
|
* @see MessageDialog#createCustomArea(Composite)
|
||||||
|
*/
|
||||||
|
protected Control createCustomArea(Composite parent) {
|
||||||
|
|
||||||
|
ScrolledComposite scrollable = new ScrolledComposite(parent, SWT.BORDER|SWT.V_SCROLL);
|
||||||
|
GridData gridData = new GridData(GridData.FILL_BOTH);
|
||||||
|
gridData.heightHint = SCROLLABLE_HEIGHT;
|
||||||
|
scrollable.setLayoutData(gridData);
|
||||||
|
scrollable.setExpandHorizontal(true);
|
||||||
|
scrollable.setExpandVertical(true);
|
||||||
|
GridLayout gridLayout = new GridLayout();
|
||||||
|
gridLayout.marginWidth = gridLayout.marginHeight = gridLayout.verticalSpacing = 0;
|
||||||
|
content = new Composite(scrollable, SWT.NONE);
|
||||||
|
content.setLayout(gridLayout);
|
||||||
|
content.setBackground(new Color(parent.getDisplay(), WHITE));
|
||||||
|
scrollable.setContent(content);
|
||||||
|
for (int index = 0; index < unterminated.length; index++) {
|
||||||
|
|
||||||
|
Composite item = createItem(content, unterminated[index]);
|
||||||
|
item.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||||
|
}
|
||||||
|
content.pack();
|
||||||
|
scrollable.setMinHeight(content.getBounds().height);
|
||||||
|
return scrollable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the {@link SelectionEvent}s that are sent when the user clicks the stop button of a
|
||||||
|
* launch. The stop button will immediately be disabled to indicate that the stop request is
|
||||||
|
* being processed. The actual launch termination will be confirmed in an asynchronous fashion
|
||||||
|
* by the {@link #launchesTerminated(ILaunch[])} method.
|
||||||
|
*
|
||||||
|
* @param event the {@link SelectionEvent}
|
||||||
|
*
|
||||||
|
* @see #launchesTerminated(ILaunch[])
|
||||||
|
*/
|
||||||
|
public void widgetSelected(SelectionEvent event) {
|
||||||
|
|
||||||
|
ToolItem item = (ToolItem)event.widget;
|
||||||
|
ILaunch launch = (ILaunch)item.getParent().getParent().getData();
|
||||||
|
item.setEnabled(false);
|
||||||
|
try {
|
||||||
|
|
||||||
|
LocalTerminalProcessRegistry.addProcessBackToFinishedLaunch(launch);
|
||||||
|
launch.terminate();
|
||||||
|
}
|
||||||
|
catch (DebugException exception) {
|
||||||
|
|
||||||
|
Logger.logException(exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles default selection events by passing them to {@link #widgetSelected(SelectionEvent)}.
|
||||||
|
*
|
||||||
|
* @param event the {@link SelectionEvent}
|
||||||
|
*
|
||||||
|
* @see #widgetSelected(SelectionEvent)
|
||||||
|
* @see SelectionListener#widgetSelected(SelectionEvent)
|
||||||
|
*/
|
||||||
|
public void widgetDefaultSelected(SelectionEvent event) {
|
||||||
|
|
||||||
|
widgetSelected(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes terminated launches from the list displayed by the dialog and closes the dialog once
|
||||||
|
* all outstanding launches have been terminated.
|
||||||
|
*
|
||||||
|
* @see #launchesTerminated(ILaunch[])
|
||||||
|
*/
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
boolean allLaunchesTerminated = true;
|
||||||
|
Control[] child = content.getChildren();
|
||||||
|
int numberOfChildren = child.length;
|
||||||
|
for (int number = 0; number < numberOfChildren; number++) {
|
||||||
|
|
||||||
|
ILaunch launch = (ILaunch)child[number].getData();
|
||||||
|
if (launch != null && launch.isTerminated()) {
|
||||||
|
|
||||||
|
child[number].setData(null);
|
||||||
|
String exitValue;
|
||||||
|
try {
|
||||||
|
|
||||||
|
exitValue = String.valueOf(launch.getProcesses()[0].getExitValue());
|
||||||
|
}
|
||||||
|
catch (DebugException couldNotGetExitValue) {
|
||||||
|
|
||||||
|
exitValue = '(' + couldNotGetExitValue.getMessage() + ')';
|
||||||
|
}
|
||||||
|
Label label = (Label)((Composite)child[number]).getChildren()[1];
|
||||||
|
String process = label.getText();
|
||||||
|
process = NLS.bind(LocalTerminalMessages.terminatedProcess, process, exitValue);
|
||||||
|
label.setText(process);
|
||||||
|
|
||||||
|
// In case the launch terminated by itself (and not because the user pressed the
|
||||||
|
// stop button) disable the stop button so that no attempt can be made to stop the
|
||||||
|
// process twice:
|
||||||
|
//
|
||||||
|
((Composite)child[number]).getChildren()[2].setEnabled(false);
|
||||||
|
}
|
||||||
|
if (child[number].getData() != null) {
|
||||||
|
|
||||||
|
allLaunchesTerminated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allLaunchesTerminated) {
|
||||||
|
|
||||||
|
setReturnCode(0);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a recently terminated launch from the list displayed by the dialog. The actual work
|
||||||
|
* needs to be done in the UI thread and is performed by the {@link #run()} method.
|
||||||
|
*
|
||||||
|
* @param terminated a list of terminated launches
|
||||||
|
*
|
||||||
|
* @see #run()
|
||||||
|
*/
|
||||||
|
public void launchesTerminated(ILaunch[] terminated) {
|
||||||
|
|
||||||
|
Display.getDefault().syncExec(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <i>Not implemented</i>.
|
||||||
|
* @see ILaunchesListener2#launchesAdded(ILaunch[])
|
||||||
|
*/
|
||||||
|
public void launchesAdded(ILaunch[] launches) {
|
||||||
|
|
||||||
|
// Not implemented...
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <i>Not implemented</i>.
|
||||||
|
* @see ILaunchesListener2#launchesChanged(ILaunch[])
|
||||||
|
*/
|
||||||
|
public void launchesChanged(ILaunch[] launches) {
|
||||||
|
|
||||||
|
// Not implemented...
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <i>Not implemented</i>.
|
||||||
|
* @see ILaunchesListener2#launchesRemoved(ILaunch[])
|
||||||
|
*/
|
||||||
|
public void launchesRemoved(ILaunch[] launches) {
|
||||||
|
|
||||||
|
// Not implemented...
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------- PRIVATE SECTION -------------------------------------//
|
||||||
|
|
||||||
|
private Composite createItem(Composite parent, ILaunch launch) {
|
||||||
|
|
||||||
|
Composite item = new Composite(parent, SWT.NULL);
|
||||||
|
GridLayout gridLayout = new GridLayout(3, false);
|
||||||
|
item.setData(launch);
|
||||||
|
item.setLayout(gridLayout);
|
||||||
|
Image processImage = LocalTerminalLaunchUtilities.getImage(launch.getLaunchConfiguration());
|
||||||
|
Label icon = new Label(item, SWT.NULL);
|
||||||
|
icon.setImage(processImage);
|
||||||
|
Label label = new Label(item, SWT.NULL);
|
||||||
|
label.setText(launch.getLaunchConfiguration().getName());
|
||||||
|
ToolItem stopButton = new ToolItem(new ToolBar(item, SWT.FLAT), SWT.PUSH);
|
||||||
|
stopButton.addSelectionListener(this);
|
||||||
|
Image deleteImage = DebugUITools.getImage(IMG_LCL_TERMINATE);
|
||||||
|
stopButton.setImage(deleteImage);
|
||||||
|
GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
|
||||||
|
gridData.verticalAlignment = GridData.CENTER;
|
||||||
|
gridData.grabExcessHorizontalSpace = true;
|
||||||
|
label.setLayoutData(gridData);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,156 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner.
|
||||||
|
* 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:
|
||||||
|
* Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local.process;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.eclipse.cdt.utils.spawner.Spawner;
|
||||||
|
import org.eclipse.debug.core.ILaunch;
|
||||||
|
import org.eclipse.debug.core.model.IProcess;
|
||||||
|
import org.eclipse.debug.core.model.IStreamsProxy;
|
||||||
|
import org.eclipse.debug.core.model.RuntimeProcess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalProcess} is a customized {@link RuntimeProcess} for use by the
|
||||||
|
* {@link org.eclipse.tm.internal.terminal.local.LocalTerminalConnector}. It serves the purpose of
|
||||||
|
* preventing the {@link org.eclipse.debug.internal.ui.DebugUIPlugin DebugUIPlugin}'s
|
||||||
|
* {@link org.eclipse.debug.internal.ui.views.console.ProcessConsoleManager ProcessConsoleManager}
|
||||||
|
* from allocating a Console view in addition to the Terminal view that serves as the program's main
|
||||||
|
* I/O device. <p>
|
||||||
|
* Unfortunately, the Process Console Manager determines the need for a Console view by checking the
|
||||||
|
* {@link IStreamsProxy} of the process for <code>null</code>. If the process has a non-null
|
||||||
|
* {@link IStreamsProxy} a console will be automatically allocated. This is problematic because
|
||||||
|
* the Local Terminal Connector requires an {@link IStreamsProxy} but obviously not an additional
|
||||||
|
* console view. It would have been better if the Process Console Manager would check the
|
||||||
|
* corresponding attributes in the launch configuration rather than checking the
|
||||||
|
* {@link IStreamsProxy} of the process. The work-around for now is to remove the underlying
|
||||||
|
* process from the launch. No console will be allocated for a launch that doesn't have a process
|
||||||
|
* associated with it. Consequently, a currently running terminal launch will appear in the Debug
|
||||||
|
* view's list of active launches but the view will not show any child elements (and the element
|
||||||
|
* cannot be expanded, either). The {@link LocalTerminalProcessRegistry} keeps track of which
|
||||||
|
* {@link LocalTerminalProcess} is associated with a particular launch. Client code that needs to
|
||||||
|
* find the process of a launch can obtain it through that registry. <p>
|
||||||
|
* However, for a launch to be properly terminated it needs to have at least one process that can
|
||||||
|
* be terminated. Launches that do not have any processes associated with them are not considered
|
||||||
|
* terminated and actually terminating them is not possible. To work around this secondary issue,
|
||||||
|
* the process is added back to its launch just before the launch is terminated. This activity is
|
||||||
|
* performed by {@link LocalTerminalProcessRegistry#addProcessBackToFinishedLaunch(ILaunch)}. To
|
||||||
|
* prevent a console allocation during this last step, the {@link #resetStreamsProxy()} method will
|
||||||
|
* be invoked, which will cause subsequent calls to {@link IProcess#getStreamsProxy()} to return
|
||||||
|
* <code>null</code>. After the launch is terminated it will appear in the Debug view with the
|
||||||
|
* terminated process as its child element. The exit value of the terminal process can also be seen
|
||||||
|
* in that view. <p>
|
||||||
|
*
|
||||||
|
* This solution for preventing standard consoles from being opened does certainly not deserve the
|
||||||
|
* cleanliness award for straightforward coding, but at least it doesn't rely on internal API at
|
||||||
|
* this point. Ideally, the whole issue should be resolved with some sort of console renderer
|
||||||
|
* extension point as proposed in bug 242373 (https://bugs.eclipse.org/bugs/show_bug.cgi?id=242373).
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.3 $
|
||||||
|
*/
|
||||||
|
public final class LocalTerminalProcess extends RuntimeProcess {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The process type ID of processes produced by this factory.
|
||||||
|
*/
|
||||||
|
public final static String PROCESS_TYPE = "org.eclipse.tm.terminal.localProcess"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private boolean resetStreamsProxy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link LocalTerminalProcess}.
|
||||||
|
*
|
||||||
|
* @param launch the current {@link ILaunch}
|
||||||
|
* @param process the underlying low-level {@link Process}
|
||||||
|
* @param name the process name
|
||||||
|
* @param attributes additional attributes of the process
|
||||||
|
*/
|
||||||
|
protected LocalTerminalProcess(ILaunch launch, Process process, String name, Map attributes) {
|
||||||
|
|
||||||
|
super(launch, process, name, setProcessType(attributes));
|
||||||
|
LocalTerminalProcessRegistry.registerWithLaunch(launch, this);
|
||||||
|
launch.removeProcess(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a <code>SIGINT</code> signal to the underlying system {@link Process}. This is roughly
|
||||||
|
* equivalent to the user pressing Ctrl-C.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the interrupt signal was sent successfully; <code>false</code>
|
||||||
|
* if the signal was not sent successfully or if no signal was sent because the underlying
|
||||||
|
* process is not a CDT {@link Spawner}
|
||||||
|
*/
|
||||||
|
public boolean interrupt() {
|
||||||
|
|
||||||
|
Process process = getSystemProcess();
|
||||||
|
if (process instanceof Spawner) {
|
||||||
|
|
||||||
|
return ((Spawner)process).interrupt() == 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link IStreamsProxy} of the process.
|
||||||
|
*
|
||||||
|
* @return the original result of {@link RuntimeProcess#getStreamsProxy()}, or <code>null</code>
|
||||||
|
* after {@link #resetStreamsProxy()} has been called.
|
||||||
|
*/
|
||||||
|
public IStreamsProxy getStreamsProxy() {
|
||||||
|
|
||||||
|
if (resetStreamsProxy) {
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return super.getStreamsProxy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the {@link IStreamsProxy} of this process. After calling this method,
|
||||||
|
* {@link #getStreamsProxy()} will always return <code>null</code>.
|
||||||
|
*/
|
||||||
|
protected void resetStreamsProxy() {
|
||||||
|
|
||||||
|
resetStreamsProxy = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-attaches the process to its launch and completes termination of the process. This ensures
|
||||||
|
* that the launch can properly terminate.
|
||||||
|
*
|
||||||
|
* @see RuntimeProcess#terminated()
|
||||||
|
*/
|
||||||
|
protected void terminated() {
|
||||||
|
|
||||||
|
LocalTerminalProcessRegistry.addProcessBackToFinishedLaunch(getLaunch());
|
||||||
|
super.terminated();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------- PRIVATE SECTION --------------------------------------//
|
||||||
|
|
||||||
|
private static Map setProcessType(Map attributes) {
|
||||||
|
|
||||||
|
// The process type used to be set by the LocalTerminalProcessFactory. However, if some
|
||||||
|
// client code managed to instantiate a LocalTerminalProcess directly (instead of going
|
||||||
|
// through the factory) this would result in IProcess objects with an incorrect process type
|
||||||
|
// attribute. A better solution is to set the process type attribute at the time when the
|
||||||
|
// LocalTerminalProcess object is actually created:
|
||||||
|
//
|
||||||
|
if (attributes == null) {
|
||||||
|
|
||||||
|
attributes = new HashMap(1);
|
||||||
|
}
|
||||||
|
attributes.put(IProcess.ATTR_PROCESS_TYPE, PROCESS_TYPE);
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner.
|
||||||
|
* 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:
|
||||||
|
* Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local.process;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import org.eclipse.debug.core.ILaunch;
|
||||||
|
import org.eclipse.debug.core.IProcessFactory;
|
||||||
|
import org.eclipse.debug.core.model.IProcess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link LocalTerminalProcessFactory} is an {@link IProcessFactory} that produces
|
||||||
|
* {@link LocalTerminalProcess} objects.
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.2 $
|
||||||
|
*/
|
||||||
|
public class LocalTerminalProcessFactory implements IProcessFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID of this factory (as used in <code>plugin.xml</code>).
|
||||||
|
*/
|
||||||
|
public final static String ID = "org.eclipse.tm.terminal.localProcess.factory"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see IProcessFactory#newProcess(ILaunch, Process, String, Map)
|
||||||
|
*/
|
||||||
|
public IProcess newProcess(ILaunch launch, Process process, String label, Map attributes) {
|
||||||
|
|
||||||
|
return new LocalTerminalProcess(launch, process, label, attributes);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,158 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner.
|
||||||
|
* 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:
|
||||||
|
* Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local.process;
|
||||||
|
|
||||||
|
import java.util.IdentityHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.eclipse.debug.core.ILaunch;
|
||||||
|
import org.eclipse.debug.core.ILaunchesListener2;
|
||||||
|
import org.eclipse.tm.internal.terminal.local.LocalTerminalUtilities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link LocalTerminalProcessRegistry} keeps a map between {@link ILaunch} objects and the
|
||||||
|
* {@link LocalTerminalProcess} objects that were associated with them. To prevent standard consoles
|
||||||
|
* from being opened, a {@link LocalTerminalProcess} is immediately removed from its {@link ILaunch}
|
||||||
|
* when the process is created (see {@link LocalTerminalProcess} for details).
|
||||||
|
* {@link LocalTerminalProcessRegistry} is a singleton (without lazy initialization).
|
||||||
|
*
|
||||||
|
* @author mirko
|
||||||
|
* @version $Revision: 1.1 $
|
||||||
|
*/
|
||||||
|
public class LocalTerminalProcessRegistry implements ILaunchesListener2 {
|
||||||
|
|
||||||
|
private final static LocalTerminalProcessRegistry INSTANCE = new LocalTerminalProcessRegistry();
|
||||||
|
|
||||||
|
private Map processes;
|
||||||
|
|
||||||
|
private LocalTerminalProcessRegistry() {
|
||||||
|
|
||||||
|
// The ILaunch interface does not make any statements about the suitability of implementing
|
||||||
|
// objects as hash keys. There might be ILaunch implementations that return a different
|
||||||
|
// hash code value if the object changes internally. To be safe in those cases, an
|
||||||
|
// IdentityHashMap is used:
|
||||||
|
//
|
||||||
|
processes = new IdentityHashMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link LocalTerminalProcess} that was originally associated with a given
|
||||||
|
* {@link ILaunch} object.
|
||||||
|
*
|
||||||
|
* @param launch the {@link ILaunch} that was used for creating the process
|
||||||
|
* @return the corresponding {@link LocalTerminalProcess}, or <code>null</code> if no process
|
||||||
|
* could be found
|
||||||
|
*/
|
||||||
|
public static LocalTerminalProcess getFromLaunch(ILaunch launch) {
|
||||||
|
|
||||||
|
return (LocalTerminalProcess)INSTANCE.processes.get(launch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a {@link LocalTerminalProcess} object back to its original {@link ILaunch}. This method
|
||||||
|
* will also perform a {@link LocalTerminalProcess#resetStreamsProxy()} on the process.
|
||||||
|
* The {@link #addProcessBackToFinishedLaunch(ILaunch)} method is necessary for properly
|
||||||
|
* terminating the launch of a terminal application (see {@link LocalTerminalProcess} for
|
||||||
|
* details).
|
||||||
|
*
|
||||||
|
* @param launch the {@link ILaunch} whose original process is to be re-attached
|
||||||
|
*/
|
||||||
|
public static void addProcessBackToFinishedLaunch(ILaunch launch) {
|
||||||
|
|
||||||
|
LocalTerminalProcess process = getFromLaunch(launch);
|
||||||
|
if (process == null) {
|
||||||
|
|
||||||
|
// Maybe the process wasn't actually started in a terminal (can happen when a Terminal
|
||||||
|
// is launched from the External Tools menu):
|
||||||
|
//
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
process.resetStreamsProxy();
|
||||||
|
if (launch.getProcesses().length == 0) {
|
||||||
|
|
||||||
|
launch.addProcess(process);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a {@link LocalTerminalProcess} with a given {@link ILaunch} so that the process can
|
||||||
|
* be safely removed from the launch.
|
||||||
|
*
|
||||||
|
* @param launch the {@link ILaunch}
|
||||||
|
* @param process the {@link LocalTerminalProcess} originally associated with that launch
|
||||||
|
*/
|
||||||
|
public static void registerWithLaunch(ILaunch launch, LocalTerminalProcess process) {
|
||||||
|
|
||||||
|
synchronized (INSTANCE) {
|
||||||
|
|
||||||
|
if (INSTANCE.processes.isEmpty()) {
|
||||||
|
|
||||||
|
// Start listening to terminated launches as soon as the first launch/process pair
|
||||||
|
// is registered:
|
||||||
|
//
|
||||||
|
LocalTerminalUtilities.LAUNCH_MANAGER.addLaunchListener(INSTANCE);
|
||||||
|
}
|
||||||
|
INSTANCE.processes.put(launch, process);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the termination of launches. The {@link LocalTerminalProcessRegistry} acts as a
|
||||||
|
* {@link ILaunchesListener2} if there are monitored launches outstanding. It will automatically
|
||||||
|
* de-register itself (as a listener) when the last monitored launch was terminated.
|
||||||
|
*
|
||||||
|
* @param terminated the launches that were terminated
|
||||||
|
*/
|
||||||
|
public void launchesTerminated(ILaunch[] terminated) {
|
||||||
|
|
||||||
|
synchronized (INSTANCE) {
|
||||||
|
|
||||||
|
int numberOfTerminatedLaunches = terminated.length;
|
||||||
|
for (int launch = 0; launch < numberOfTerminatedLaunches; launch++) {
|
||||||
|
|
||||||
|
INSTANCE.processes.remove(terminated[launch]);
|
||||||
|
}
|
||||||
|
if (INSTANCE.processes.isEmpty()) {
|
||||||
|
|
||||||
|
// If there are no more outstanding launches the listener can be removed again:
|
||||||
|
//
|
||||||
|
LocalTerminalUtilities.LAUNCH_MANAGER.removeLaunchListener(INSTANCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <i>Not implemented</i>.
|
||||||
|
* @see ILaunchesListener2#launchesAdded(ILaunch[])
|
||||||
|
*/
|
||||||
|
public void launchesAdded(ILaunch[] launches) {
|
||||||
|
|
||||||
|
// Not implemented.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <i>Not implemented</i>.
|
||||||
|
* @see ILaunchesListener2#launchesRemoved(ILaunch[])
|
||||||
|
*/
|
||||||
|
public void launchesRemoved(ILaunch[] launches) {
|
||||||
|
|
||||||
|
// Not implemented.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <i>Not implemented</i>.
|
||||||
|
* @see ILaunchesListener2#launchesChanged(ILaunch[])
|
||||||
|
*/
|
||||||
|
public void launchesChanged(ILaunch[] launches) {
|
||||||
|
|
||||||
|
// Not implemented.
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) 2008 Mirko Raner.
|
||||||
|
* 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:
|
||||||
|
* Mirko Raner - initial implementation for Eclipse Bug 196337
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.tm.internal.terminal.local.ui;
|
||||||
|
|
||||||
|
import org.eclipse.swt.events.ControlEvent;
|
||||||
|
import org.eclipse.swt.events.ControlListener;
|
||||||
|
import org.eclipse.swt.graphics.Point;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class {@link DependentHeightComposite} is a special kind of SWT {@link Composite} whose
|
||||||
|
* height depends on the height of some master {@link Composite} that does not have to be a direct
|
||||||
|
* parent or child of it. This class was introduced as a work-around for UI resizing problems with
|
||||||
|
* the Terminal API's PageBook class (which uses a StackLayout).
|
||||||
|
*
|
||||||
|
* @author Mirko Raner
|
||||||
|
* @version $Revision: 1.1 $
|
||||||
|
*/
|
||||||
|
public class DependentHeightComposite extends Composite implements ControlListener {
|
||||||
|
|
||||||
|
private Composite master;
|
||||||
|
private int preferredHeight = -1;
|
||||||
|
private int extraHeight;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link DependentHeightComposite}.
|
||||||
|
*
|
||||||
|
* @param parent the parent {@link Composite}
|
||||||
|
* @param style the SWT style
|
||||||
|
* @param master the master {@link Composite} that determines the height
|
||||||
|
* @param extra the additional height in pixels (may be negative, to create a smaller height
|
||||||
|
* than the master {@link Composite})
|
||||||
|
*/
|
||||||
|
public DependentHeightComposite(Composite parent, int style, Composite master, int extra) {
|
||||||
|
|
||||||
|
super(parent, style);
|
||||||
|
this.master = master;
|
||||||
|
this.extraHeight = extra;
|
||||||
|
master.addControlListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method does nothing.
|
||||||
|
*
|
||||||
|
* @see ControlListener#controlMoved(ControlEvent)
|
||||||
|
*/
|
||||||
|
public void controlMoved(ControlEvent event) {
|
||||||
|
|
||||||
|
// Does nothing...
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjusts the {@link DependentHeightComposite} height if the master {@link Composite}'s size
|
||||||
|
* changed.
|
||||||
|
*
|
||||||
|
* @param event the {@link ControlEvent}
|
||||||
|
*/
|
||||||
|
public void controlResized(ControlEvent event) {
|
||||||
|
|
||||||
|
setSize(getSize().x, master.getClientArea().height+extraHeight);
|
||||||
|
preferredHeight = master.getClientArea().height+extraHeight;
|
||||||
|
master.layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the preferred size of this {@link DependentHeightComposite}.
|
||||||
|
*
|
||||||
|
* @see Composite#computeSize(int, int, boolean)
|
||||||
|
*/
|
||||||
|
public Point computeSize(int widthHint, int heightHint, boolean changed) {
|
||||||
|
|
||||||
|
Point size = super.computeSize(widthHint, heightHint, changed);
|
||||||
|
if (preferredHeight != -1) {
|
||||||
|
|
||||||
|
size.y = preferredHeight;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue