Revert "bug 400237: Fixed deployment of plain web applications with strange symbols in the name (such as ‘ ‘, ‘%’, ‘~’)"
This reverts commit 367965154828f90c38d636bea4dd37506c4d1939.
diff --git a/org.eclipse.virgo.web.war.deployer/.classpath b/org.eclipse.virgo.web.war.deployer/.classpath
index 30bc4f2..4f0064f 100644
--- a/org.eclipse.virgo.web.war.deployer/.classpath
+++ b/org.eclipse.virgo.web.war.deployer/.classpath
@@ -34,6 +34,5 @@
<classpathentry kind="var" path="IVY_CACHE/org.eclipse.virgo.nano/org.eclipse.virgo.nano.deployer/3.7.0.D-20130226164727/org.eclipse.virgo.nano.deployer-3.7.0.D-20130226164727.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.eclipse.virgo.nano/org.eclipse.virgo.nano.core/3.7.0.D-20130226164727/org.eclipse.virgo.nano.core-3.7.0.D-20130226164727.jar" sourcepath="/IVY_CACHE/org.eclipse.virgo.kernel/org.eclipse.virgo.nano.core/3.7.0.D-20130226164727/org.eclipse.virgo.nano.core-sources-3.7.0.D-20130226164727.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.eclipse.gemini/org.eclipse.gemini.web.core/2.2.1.RELEASE/org.eclipse.gemini.web.core-2.2.1.RELEASE.jar"/>
- <classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
diff --git a/org.eclipse.virgo.web.war.deployer/ivy.xml b/org.eclipse.virgo.web.war.deployer/ivy.xml
index 025fb14..2739f6c 100644
--- a/org.eclipse.virgo.web.war.deployer/ivy.xml
+++ b/org.eclipse.virgo.web.war.deployer/ivy.xml
@@ -20,7 +20,6 @@
<dependency org="org.eclipse.virgo.util" name="org.eclipse.virgo.util.osgi.manifest" rev="${org.eclipse.virgo.util}" conf="compile->runtime"/>
<dependency org="org.eclipse.gemini" name="org.eclipse.gemini.web.core" rev="${org.eclipse.gemini.web}" conf="compile->runtime"/>
<dependency org="org.eclipse.virgo.medic" name="org.eclipse.virgo.medic" rev="${org.eclipse.virgo.medic}" conf="compile->runtime"/>
- <dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit}" conf="test->runtime"/>
<override org="org.eclipse.virgo.util" rev="${org.eclipse.virgo.util}"/>
<!-- Allow Equinox to be upgraded point-wise before rippling -->
diff --git a/org.eclipse.virgo.web.war.deployer/src/main/java/org/eclipse/virgo/web/war/deployer/WARDeployer.java b/org.eclipse.virgo.web.war.deployer/src/main/java/org/eclipse/virgo/web/war/deployer/WARDeployer.java
index 274aecf..798c9d9 100644
--- a/org.eclipse.virgo.web.war.deployer/src/main/java/org/eclipse/virgo/web/war/deployer/WARDeployer.java
+++ b/org.eclipse.virgo.web.war.deployer/src/main/java/org/eclipse/virgo/web/war/deployer/WARDeployer.java
@@ -172,16 +172,15 @@
this.eventLogger.log(WARDeployerLogEvents.NANO_INSTALLING, new File(path).toString());
final String warName = extractDecodedWarNameFromString(path.toString());
final File deployedFile = new File(path);
- String extractionFolderName = WebBundleUtils.calculateCorrectSymbolicName(warName);
- final File warDir = new File(this.webAppsDir, extractionFolderName);
- StatusFileModificator.deleteStatusFile(extractionFolderName, this.pickupDir);
+ final File warDir = new File(this.webAppsDir, replaceHashSigns(warName, DOT));
+ StatusFileModificator.deleteStatusFile(warName, this.pickupDir);
long bundleId = -1L;
final long lastModified = deployedFile.lastModified();
if (!canWrite(path)) {
this.logger.error("Cannot open the file " + path + " for writing. The configured timeout is " + this.largeFileCopyTimeout + ".");
- StatusFileModificator.createStatusFile(extractionFolderName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
+ StatusFileModificator.createStatusFile(warName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
this.eventLogger.log(WARDeployerLogEvents.NANO_INSTALLING_ERROR, path);
return STATUS_ERROR;
}
@@ -196,7 +195,7 @@
installed = this.bundleContext.installBundle(BundleLocationUtil.createInstallLocation(this.kernelHomeFile, warDir));
} catch (Exception e) {
this.eventLogger.log(WARDeployerLogEvents.NANO_INSTALLING_ERROR, e, path);
- StatusFileModificator.createStatusFile(extractionFolderName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
+ StatusFileModificator.createStatusFile(warName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
return STATUS_ERROR;
}
@@ -206,7 +205,7 @@
installed.start();
} catch (Exception e) {
this.eventLogger.log(WARDeployerLogEvents.NANO_STARTING_ERROR, e, installed.getSymbolicName(), installed.getVersion());
- StatusFileModificator.createStatusFile(extractionFolderName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
+ StatusFileModificator.createStatusFile(warName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
return STATUS_ERROR;
}
@@ -220,15 +219,15 @@
try {
if (this.bundleInfosUpdaterUtil != null && this.bundleInfosUpdaterUtil.isAvailable()) {
- BundleInfosUpdater.registerToBundlesInfo(installed, getLocationForBundlesInfo(extractionFolderName), NOT_A_FRAGMENT);
+ BundleInfosUpdater.registerToBundlesInfo(installed, getLocationForBundlesInfo(path), NOT_A_FRAGMENT);
}
} catch (Exception e) {
this.eventLogger.log(WARDeployerLogEvents.NANO_PERSIST_ERROR, e, installed.getSymbolicName(), installed.getVersion());
- StatusFileModificator.createStatusFile(extractionFolderName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
+ StatusFileModificator.createStatusFile(warName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
return STATUS_ERROR;
}
- StatusFileModificator.createStatusFile(extractionFolderName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_OK, bundleId, lastModified);
+ StatusFileModificator.createStatusFile(warName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_OK, bundleId, lastModified);
return STATUS_OK;
}
@@ -261,10 +260,11 @@
public final boolean undeploy(Bundle bundle) {
String bundleLocation = removeTrailingFileSeparator(bundle.getLocation());
String warPath = extractWarPath(bundleLocation);
- String extractionFolderName = extractWarNameFromBundleLocation(warPath);
- final File warDir = new File(warPath);
+ final File warDir = new File(replaceHashSigns(warPath, DOT));
+ String warName = extractWarNameFromBundleLocation(warPath);
- StatusFileModificator.deleteStatusFile(extractionFolderName, this.pickupDir);
+ String statusFilePrefix = calculateStatusFilePrefix(bundle, warName);
+ StatusFileModificator.deleteStatusFile(statusFilePrefix, this.pickupDir);
if (bundle != null) {
try {
@@ -286,12 +286,12 @@
this.eventLogger.log(WARDeployerLogEvents.NANO_UNINSTALLING, bundle.getSymbolicName(), bundle.getVersion());
bundle.uninstall();
// we need to decode the path before delete or a /webapps entry might leak
- FileSystemUtils.deleteRecursively(new File(warDir.getAbsolutePath()));
+ FileSystemUtils.deleteRecursively(new File(URLDecoder.decode(warDir.getAbsolutePath())));
this.eventLogger.log(WARDeployerLogEvents.NANO_UNINSTALLED, bundle.getSymbolicName(), bundle.getVersion());
wabStates.remove((String)bundle.getSymbolicName());
} catch (BundleException e) {
this.eventLogger.log(WARDeployerLogEvents.NANO_UNDEPLOY_ERROR, e, bundle.getSymbolicName(), bundle.getVersion());
- StatusFileModificator.createStatusFile(extractionFolderName, this.pickupDir, StatusFileModificator.OP_UNDEPLOY, STATUS_ERROR, -1, -1);
+ StatusFileModificator.createStatusFile(statusFilePrefix, this.pickupDir, StatusFileModificator.OP_UNDEPLOY, STATUS_ERROR, -1, -1);
return STATUS_ERROR;
} catch (IOException e) {
this.eventLogger.log(WARDeployerLogEvents.NANO_PERSIST_ERROR, e, bundle.getSymbolicName(), bundle.getVersion());
@@ -300,7 +300,7 @@
}
}
- StatusFileModificator.createStatusFile(extractionFolderName, this.pickupDir, StatusFileModificator.OP_UNDEPLOY, STATUS_OK, -1, -1);
+ StatusFileModificator.createStatusFile(statusFilePrefix, this.pickupDir, StatusFileModificator.OP_UNDEPLOY, STATUS_OK, -1, -1);
return STATUS_OK;
}
@@ -347,9 +347,8 @@
@Override
public final boolean update(URI path) {
final String warName = extractDecodedWarNameFromString(path.toString());
- String extractionFolderName = WebBundleUtils.calculateCorrectSymbolicName(warName);
final File updatedFile = new File(path);
- final File warDir = new File(this.webAppsDir, extractionFolderName);
+ final File warDir = new File(this.webAppsDir, replaceHashSigns(warName, DOT));
if (!warDir.exists()) {
this.logger.info("Can't update artifact for path '" + path + "'. It is not deployed.");
@@ -357,14 +356,14 @@
final boolean isOfflineUpdated = isOfflineUpdated(path);
- StatusFileModificator.deleteStatusFile(extractionFolderName, this.pickupDir);
+ StatusFileModificator.deleteStatusFile(warName, this.pickupDir);
final long bundleId = -1L;
final long lastModified = updatedFile.lastModified();
if (!canWrite(path)) {
this.logger.error("Cannot open the file [" + path + "] for writing. Timeout is [" + this.largeFileCopyTimeout + "].");
- StatusFileModificator.createStatusFile(extractionFolderName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
+ StatusFileModificator.createStatusFile(warName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
this.eventLogger.log(WARDeployerLogEvents.NANO_UPDATING_ERROR, path);
return STATUS_ERROR;
}
@@ -375,7 +374,7 @@
boolean isLegalState = checkWabState(bundle, isOfflineUpdated);
if (isLegalState == false) {
this.eventLogger.log(WARDeployerLogEvents.NANO_UPDATE_STATE_ERROR, bundle.getSymbolicName(), bundle.getVersion());
- StatusFileModificator.createStatusFile(extractionFolderName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
+ StatusFileModificator.createStatusFile(warName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
return STATUS_ERROR;
}
wabStates.put(bundle.getSymbolicName(), "");
@@ -398,10 +397,10 @@
this.eventLogger.log(WARDeployerLogEvents.NANO_UPDATED, bundle.getSymbolicName(), bundle.getVersion());
} catch (Exception e) {
this.eventLogger.log(WARDeployerLogEvents.NANO_UPDATE_ERROR, e, bundle.getSymbolicName(), bundle.getVersion());
- StatusFileModificator.createStatusFile(extractionFolderName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
+ StatusFileModificator.createStatusFile(warName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundleId, lastModified);
return STATUS_ERROR;
}
- StatusFileModificator.createStatusFile(extractionFolderName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_OK, bundleId, lastModified);
+ StatusFileModificator.createStatusFile(warName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_OK, bundleId, lastModified);
} else {
deploy(path);
}
@@ -560,7 +559,7 @@
@Override
public boolean isDeployed(URI path) {
final String warName = extractDecodedWarNameFromString(path.toString());
- final File warDir = new File(this.webAppsDir, WebBundleUtils.calculateCorrectSymbolicName(warName));
+ final File warDir = new File(this.webAppsDir, replaceHashSigns(warName, DOT));
if (!warDir.exists()) {
return false;
}
@@ -575,7 +574,7 @@
final String warName = extractDecodedWarNameFromString(path.toString());
final File deployFile = new File(path);
long deployFileLastModified = deployFile.lastModified();
- long lastModifiedStatus = StatusFileModificator.getLastModifiedFromStatusFile(WebBundleUtils.calculateCorrectSymbolicName(warName), this.pickupDir);
+ long lastModifiedStatus = StatusFileModificator.getLastModifiedFromStatusFile(warName, this.pickupDir);
if (lastModifiedStatus == -1 || deployFileLastModified == lastModifiedStatus) {
return false;
}
@@ -585,7 +584,7 @@
@Override
public DeploymentIdentity getDeploymentIdentity(URI path) {
final String warName = extractDecodedWarNameFromString(path.toString());
- final File warDir = new File(this.webAppsDir, WebBundleUtils.calculateCorrectSymbolicName(warName));
+ final File warDir = new File(this.webAppsDir, replaceHashSigns(warName, DOT));
if (!warDir.exists()) {
return null;
}
@@ -701,14 +700,13 @@
this.eventLogger.log(WARDeployerLogEvents.NANO_INSTALLING, new File(uri).toString());
final String warName = extractDecodedWarNameFromString(uri.toString());
final File deployedFile = new File(uri);
- String extractionFolderName = WebBundleUtils.calculateCorrectSymbolicName(warName);
- final File warDir = new File(this.webAppsDir, extractionFolderName);
- StatusFileModificator.deleteStatusFile(extractionFolderName, this.pickupDir);
+ final File warDir = new File(this.webAppsDir, replaceHashSigns(warName, DOT));
+ StatusFileModificator.deleteStatusFile(warName, this.pickupDir);
final long lastModified = deployedFile.lastModified();
if (!canWrite(uri)) {
this.logger.error("Cannot open the file " + uri + " for writing. The configured timeout is " + this.largeFileCopyTimeout + ".");
- StatusFileModificator.createStatusFile(extractionFolderName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, -1L, lastModified);
+ StatusFileModificator.createStatusFile(warName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, -1L, lastModified);
this.eventLogger.log(WARDeployerLogEvents.NANO_INSTALLING_ERROR, uri);
return false;
}
@@ -723,7 +721,7 @@
this.eventLogger.log(WARDeployerLogEvents.NANO_INSTALLED, installed.getSymbolicName(), installed.getVersion());
} catch (Exception e) {
this.eventLogger.log(WARDeployerLogEvents.NANO_INSTALLING_ERROR, e, uri);
- StatusFileModificator.createStatusFile(extractionFolderName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, -1L, lastModified);
+ StatusFileModificator.createStatusFile(warName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, -1L, lastModified);
return false;
}
return true;
@@ -731,33 +729,33 @@
@Override
public boolean start(URI uri) {
- String extractionFolderName = WebBundleUtils.calculateCorrectSymbolicName(extractDecodedWarNameFromString(uri.toString()));
- Bundle bundle = getInstalledBundle(extractionFolderName);
+ Bundle bundle = getInstalledBundle(uri);
if (bundle == null) {
this.eventLogger.log(WARDeployerLogEvents.NANO_STARTING_ERROR, uri);
logger.error("Cannot start deployable with URI + [" + uri + "]. There is no bundle installed with this URI.");
return false;
}
- StatusFileModificator.deleteStatusFile(extractionFolderName, this.pickupDir);
+ final String warName = extractDecodedWarNameFromString(uri.toString());
+ StatusFileModificator.deleteStatusFile(warName, this.pickupDir);
final long lastModified = new File(uri).lastModified();
this.eventLogger.log(WARDeployerLogEvents.NANO_WEB_STARTING, bundle.getSymbolicName(), bundle.getVersion());
try {
bundle.start();
} catch (Exception e) {
this.eventLogger.log(WARDeployerLogEvents.NANO_STARTING_ERROR, e, bundle.getSymbolicName(), bundle.getVersion());
- StatusFileModificator.createStatusFile(extractionFolderName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundle.getBundleId(),
+ StatusFileModificator.createStatusFile(warName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundle.getBundleId(),
lastModified);
return STATUS_ERROR;
}
this.eventLogger.log(WARDeployerLogEvents.NANO_WEB_STARTED, bundle.getSymbolicName(), bundle.getVersion());
// now update bundle's info
- if (!updateBundlesInfo(bundle, getLocationForBundlesInfo(extractionFolderName))) {
- StatusFileModificator.createStatusFile(extractionFolderName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundle.getBundleId(),
+ if (!updateBundlesInfo(bundle, getLocationForBundlesInfo(uri))) {
+ StatusFileModificator.createStatusFile(warName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_ERROR, bundle.getBundleId(),
lastModified);
return STATUS_ERROR;
}
- StatusFileModificator.createStatusFile(extractionFolderName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_OK, bundle.getBundleId(),
+ StatusFileModificator.createStatusFile(warName, this.pickupDir, StatusFileModificator.OP_DEPLOY, STATUS_OK, bundle.getBundleId(),
lastModified);
return STATUS_OK;
}
@@ -777,20 +775,23 @@
return STATUS_OK;
}
- private Bundle getInstalledBundle(String extractionFolderName) {
- final File warDir = new File(this.webAppsDir, extractionFolderName);
+ private Bundle getInstalledBundle(URI path) {
+ final String warName = extractDecodedWarNameFromString(path.toString());
+
+ final File warDir = new File(this.webAppsDir, replaceHashSigns(warName, DOT));
if (!warDir.exists()) {
- logger.warn("Directory with name [" + extractionFolderName + "] cannot be found in web applications directory."
+ logger.warn("Directory with name [" + warName + "] cannot be found in web applications directory."
+ " See logs for previous failures during install.");
return null;
}
return this.bundleContext.getBundle(BundleLocationUtil.createInstallLocation(this.kernelHomeFile, warDir));
}
- private String getLocationForBundlesInfo(String extractionFolderName) {
- final File warDir = new File(this.webAppsDir, extractionFolderName);
+ private String getLocationForBundlesInfo(URI path) {
+ final String warName = extractDecodedWarNameFromString(path.toString());
+ final File warDir = new File(this.webAppsDir, replaceHashSigns(warName, DOT));
if (!warDir.exists()) {
- logger.warn("Directory with name [" + extractionFolderName + "] cannot be found in web applications directory."
+ logger.warn("Directory with name [" + warName + "] cannot be found in web applications directory."
+ " See logs for previous failures during install.");
return null;
}
@@ -800,8 +801,7 @@
private String replaceHashSigns(String str, char newChar) {
return str.replace(HASH_SIGN, newChar);
}
-
-
+
class WebContainerEventsHandler implements EventHandler {
@Override
diff --git a/org.eclipse.virgo.web.war.deployer/src/main/java/org/eclipse/virgo/web/war/deployer/WebBundleUtils.java b/org.eclipse.virgo.web.war.deployer/src/main/java/org/eclipse/virgo/web/war/deployer/WebBundleUtils.java
index 605f8af..18a5b78 100644
--- a/org.eclipse.virgo.web.war.deployer/src/main/java/org/eclipse/virgo/web/war/deployer/WebBundleUtils.java
+++ b/org.eclipse.virgo.web.war.deployer/src/main/java/org/eclipse/virgo/web/war/deployer/WebBundleUtils.java
@@ -19,42 +19,6 @@
return specifiesBundleSymbolicName(manifest) || specifiesBundleVersion(manifest) || specifiesBundleManifestVersion(manifest)
|| specifiesImportPackage(manifest) || specifiesWebContextPath(manifest);
}
-
- /**
- * Transforms the input string into a string with valid characters for a
- * bundle symbolic name (valid characters are all alphanumerics plus '.',
- * '_', '-'). All forbidden characters are replaced with '.'.
- */
- public static String calculateCorrectSymbolicName(String originalName) {
- if (originalName != null) {
- return replaceForbiddenChars(originalName, '.');
- } else {
- return "";
- }
- }
-
- private static String replaceForbiddenChars(String st, char newChar) {
- char[] inpuStringChars = st.toCharArray();
- StringBuilder sb = new StringBuilder();
- for (char currentChar : inpuStringChars) {
- if (isCharAllowedInSymbolicNames(currentChar)) {
- sb.append(currentChar);
- } else {
- sb.append(newChar);
- }
- }
- return sb.toString();
- }
-
- private static boolean isCharAllowedInSymbolicNames(char ch) {
- if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
- || (ch >= '0' && ch <= '9') || ch == '_' || ch == '-'
- || ch == '.') {
- return true;
- } else {
- return false;
- }
- }
private static boolean specifiesBundleSymbolicName(BundleManifest manifest) {
return manifest.getBundleSymbolicName().getSymbolicName() != null;
diff --git a/org.eclipse.virgo.web.war.deployer/src/test/java/org/eclipse/virgo/web/war/deployer/WebBundleUtilsTest.java b/org.eclipse.virgo.web.war.deployer/src/test/java/org/eclipse/virgo/web/war/deployer/WebBundleUtilsTest.java
deleted file mode 100644
index 58c0e43..0000000
--- a/org.eclipse.virgo.web.war.deployer/src/test/java/org/eclipse/virgo/web/war/deployer/WebBundleUtilsTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2013 SAP AG
- * 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:
- * SAP AG - initial contribution
- *******************************************************************************/
-
-package org.eclipse.virgo.web.war.deployer;
-
-import org.junit.Test;
-import static org.junit.Assert.assertTrue;
-
-public class WebBundleUtilsTest {
-
- @Test
- public void calculateCorrectSymbolicNameTest() throws Exception {
- assertTrue(WebBundleUtils.calculateCorrectSymbolicName("").equals(""));
- assertTrue(WebBundleUtils.calculateCorrectSymbolicName(null).equals(""));
- assertTrue(WebBundleUtils.calculateCorrectSymbolicName("a._-1 %$#~")
- .equals("a._-1....."));
- }
-}