Skip to content

Commit afe9c10

Browse files
fixing structured app discovery (#1375)
1 parent af8e7a0 commit afe9c10

File tree

5 files changed

+233
-162
lines changed

5 files changed

+233
-162
lines changed

core/src/main/java/oracle/weblogic/deploy/util/FileUtils.java

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.security.NoSuchAlgorithmException;
2020
import java.util.ArrayList;
2121
import java.util.Arrays;
22+
import java.util.Collections;
2223
import java.util.HashSet;
2324
import java.util.List;
2425
import java.util.Locale;
@@ -637,6 +638,40 @@ public static PrintWriter getPrintWriter(String fileName) {
637638
}
638639
}
639640

641+
/**
642+
* Set OS file permissions given an Octal permission set.
643+
* Needed due to Jython 2.2 did not offer an os.chmod function.
644+
* @param path file name to be changed
645+
* @param octals octal number set like OS chmod permissions
646+
* @throws IOException if permissions update fails
647+
*/
648+
public static void chmod(String path, int octals) throws IOException {
649+
if(!WINDOWS) {
650+
Files.setPosixFilePermissions(Paths.get(path), getPermissions(octals));
651+
}
652+
}
653+
654+
public static String getCommonRootDirectory(File firstDir, File secondDir) {
655+
if (firstDir == null || secondDir == null) {
656+
return null;
657+
}
658+
659+
String[] firstDirComponents = getFileComponents(firstDir);
660+
String[] secondDirComponents = getFileComponents(secondDir);
661+
int maxLength = Math.min(firstDirComponents.length, secondDirComponents.length);
662+
663+
List<String> resultComponents = new ArrayList<>();
664+
for (int i = 0; i < maxLength; i++) {
665+
if (firstDirComponents[i].equals(secondDirComponents[i])) {
666+
resultComponents.add(firstDirComponents[i]);
667+
} else {
668+
break;
669+
}
670+
}
671+
File result = getFileFromComponents(resultComponents.toArray(new String[0]));
672+
return result != null ? getCanonicalPath(result) : null;
673+
}
674+
640675
///////////////////////////////////////////////////////////////////////////
641676
// Private helper methods //
642677
///////////////////////////////////////////////////////////////////////////
@@ -724,7 +759,6 @@ public boolean accept(File dir, String name) {
724759
}
725760
}
726761

727-
728762
/**
729763
* Convert an octal number into Posix File Permissions.
730764
* @param octals 3 octal digits representing posix file permissions rwxrwxrwx
@@ -763,16 +797,37 @@ static Set<PosixFilePermission> getPermissions(int octals) {
763797
return result;
764798
}
765799

766-
/**
767-
* Set OS file permissions given an Octal permission set.
768-
* Needed due to Jython 2.2 did not offer a os.chmod function.
769-
* @param path file name to be changed
770-
* @param octals octal number set like OS chmod permissions
771-
* @throws IOException if permissions update fails
772-
*/
773-
public static void chmod(String path, int octals) throws IOException {
774-
if(!WINDOWS) {
775-
Files.setPosixFilePermissions(Paths.get(path), getPermissions(octals));
800+
private static String[] getFileComponents(File file) {
801+
String[] result;
802+
if (file != null) {
803+
File canonicalFile = getCanonicalFile(file);
804+
List<String> names = new ArrayList<>();
805+
while(true) {
806+
File parent = canonicalFile.getParentFile();
807+
if (parent == null) {
808+
names.add(canonicalFile.getPath());
809+
break;
810+
} else {
811+
names.add(canonicalFile.getName());
812+
canonicalFile = parent;
813+
}
814+
}
815+
Collections.reverse(names);
816+
result = names.toArray(new String[0]);
817+
} else {
818+
result = new String[0];
776819
}
820+
return result;
821+
}
822+
823+
private static File getFileFromComponents(String[] components) {
824+
File result = null;
825+
if (components != null && components.length > 0) {
826+
result = new File(components[0]);
827+
for (int i = 1; i < components.length; i++) {
828+
result = new File(result, components[i]);
829+
}
830+
}
831+
return result;
777832
}
778833
}

core/src/main/java/oracle/weblogic/deploy/util/WLSDeployArchive.java

Lines changed: 50 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -370,18 +370,6 @@ public static String getDomainBinScriptArchivePath(String domainBinPath) {
370370
return getArchiveName(ARCHIVE_DOM_BIN_TARGET_DIR, domainBinPath);
371371
}
372372

373-
/**
374-
* Get the archive path for the application in a well-formed application directory
375-
*
376-
* @param appPath name of the application path
377-
* @return archive path for use in the model
378-
*/
379-
public static String getApplicationDirectoryArchivePath(String appName, String appPath) {
380-
File zipAppPath = new File(appPath).getParentFile();
381-
File zipAppFile = new File(appPath);
382-
return ARCHIVE_STRUCT_APPS_TARGET_DIR + "/" + appName + "/" + zipAppPath.getName() + "/" + zipAppFile.getName();
383-
}
384-
385373
/**
386374
* Get the archive path for the classpath library for use in the model.
387375
*
@@ -403,15 +391,57 @@ public static String getApplicationPlanArchivePath(String planFile) {
403391
}
404392

405393
/**
406-
* Get the archive path of a well-formed plan directory in app directory,
394+
* Convert the provided structured application's application installation directory into the
395+
* proper archive path.
407396
*
408-
* @param appName The application name of the app directory
409-
* @param planDir The deployment plan file directory
410-
* @return Archive path for use in the model
397+
* @param installRoot the full path to the structured application install directory on the file system
398+
* @return the converted application installation directory or null if there is no parent directory
399+
*/
400+
public static String getStructuredApplicationArchivePath(String installRoot) {
401+
final String METHOD = "getStructuredApplicationArchivePath";
402+
LOGGER.entering(CLASS, METHOD, installRoot);
403+
404+
String installRootDir = FileUtils.getCanonicalPath(installRoot);
405+
String installParentDir = new File(installRootDir).getParent();
406+
String result = null;
407+
if (!StringUtils.isEmpty(installParentDir)) {
408+
result = installRootDir.replace(installParentDir, ARCHIVE_STRUCT_APPS_TARGET_DIR);
409+
}
410+
411+
LOGGER.exiting(CLASS, METHOD, result);
412+
return result;
413+
}
414+
415+
/**
416+
* Convert the provided fileName into the proper archive path based on the application
417+
* installation directory of the structured application.
418+
*
419+
* @param originalInstallRoot the full path to the structured application install directory on the file system
420+
* @param newInstallRoot the path to the structured application install directory in the archive file
421+
* @param fileName the file name to convert
422+
* @return the converted file name if the fileName starts with the installRoot; if not, the original file name
411423
*/
412-
public static String getApplicationPlanDirArchivePath(String appName, String planDir) {
413-
File zipPath = new File(planDir);
414-
return ARCHIVE_STRUCT_APPS_TARGET_DIR + "/" + appName + "/" + zipPath.getName();
424+
public static String getStructuredApplicationArchivePath(String originalInstallRoot, String newInstallRoot,
425+
String fileName) {
426+
final String METHOD = "getStructuredApplicationArchivePath";
427+
LOGGER.entering(CLASS, METHOD, originalInstallRoot, newInstallRoot, fileName);
428+
429+
String result = fileName;
430+
File file = new File(fileName);
431+
if (file.isAbsolute() && fileName.startsWith(originalInstallRoot) && !StringUtils.isEmpty(newInstallRoot)) {
432+
String originalRoot = originalInstallRoot;
433+
if (originalInstallRoot.endsWith(File.separator) || originalInstallRoot.endsWith(ZIP_SEP)) {
434+
originalRoot = originalInstallRoot.substring(0, originalInstallRoot.length() - 1);
435+
}
436+
String newRoot = newInstallRoot;
437+
if (newInstallRoot.endsWith(File.separator) || newInstallRoot.endsWith(ZIP_SEP)) {
438+
newRoot = newInstallRoot.substring(0, newInstallRoot.length() - 1);
439+
}
440+
result = fileName.replace(originalRoot, newRoot);
441+
}
442+
443+
LOGGER.exiting(CLASS, METHOD, result);
444+
return result;
415445
}
416446

417447
/**
@@ -1216,13 +1246,11 @@ public int removeApplicationDeploymentPlan(String planPath, boolean silent) thro
12161246
* @throws IllegalArgumentException if the directory passed or its app subdirectory does not exist
12171247
*/
12181248
public String addStructuredApplication(String installRoot) throws WLSDeployArchiveIOException {
1219-
final String METHOD = "addApplicationFolder";
1249+
final String METHOD = "addStructuredApplication";
12201250
LOGGER.entering(CLASS, METHOD, installRoot);
12211251

12221252
File filePath = FileUtils.getCanonicalFile(installRoot);
1223-
File appDir = new File(filePath, "app");
12241253
validateExistingDirectory(filePath, "installRoot", getArchiveFileName(), METHOD);
1225-
validateExistingDirectory(appDir, "appDir", getArchiveFileName(), METHOD);
12261254

12271255
String newName = addItemToZip(ARCHIVE_STRUCT_APPS_TARGET_DIR, filePath);
12281256
LOGGER.exiting(CLASS, METHOD, newName);
@@ -1291,36 +1319,6 @@ public void extractStructuredApplication(String appPath, File domainHome) throws
12911319
LOGGER.exiting(CLASS, METHOD);
12921320
}
12931321

1294-
// TODO - Need to verify that discovery produces an archive that is consistent with the add/replace methods above.
1295-
// Once verified, change method name to be consistent and add javadoc.
1296-
public String addApplicationFolder(String appName, String appPath)
1297-
throws WLSDeployArchiveIOException {
1298-
final String METHOD = "addApplicationFolder";
1299-
LOGGER.entering(CLASS, METHOD, appName, appPath);
1300-
File zipPath = new File(appPath);
1301-
if (zipPath.getParentFile() != null) {
1302-
zipPath = zipPath.getParentFile();
1303-
}
1304-
String firstPrefix = ARCHIVE_STRUCT_APPS_TARGET_DIR + ZIP_SEP + appName + ZIP_SEP + zipPath.getName();
1305-
String newName = walkDownFolders(firstPrefix, zipPath);
1306-
LOGGER.exiting(CLASS, METHOD, newName);
1307-
return newName;
1308-
}
1309-
1310-
// TODO - Need to verify that discovery produces an archive that is consistent with the add/replace methods above.
1311-
// Once verified, change method name to be consistent and add javadoc.
1312-
public String addApplicationPlanFolder(String appName, String planDir)
1313-
throws WLSDeployArchiveIOException {
1314-
final String METHOD = "addApplicationPathFolder";
1315-
LOGGER.entering(CLASS, METHOD, appName, planDir);
1316-
File zipPlan = new File(planDir);
1317-
String zipPrefix = ARCHIVE_STRUCT_APPS_TARGET_DIR + ZIP_SEP + appName + ZIP_SEP + zipPlan.getName();
1318-
String newName = walkDownFolders(zipPrefix, zipPlan);
1319-
1320-
LOGGER.exiting(CLASS, METHOD, newName);
1321-
return zipPrefix;
1322-
}
1323-
13241322
/**
13251323
* Remove the named structured application from the archive file. If this is the only entry
13261324
* in the archive file directory, the directory entry will also be removed, if present.
@@ -4785,20 +4783,6 @@ private boolean filterEntry(String entry, String prefix, String name, FileOrDire
47854783
return result;
47864784
}
47874785

4788-
// TODO - remove me and replace calls with addItemToZip() to get the correct behavior.
4789-
private String walkDownFolders(String zipPrefix, File zipPath) throws WLSDeployArchiveIOException {
4790-
String newSourceName = null;
4791-
if (zipPath != null) {
4792-
File[] fileList = zipPath.listFiles();
4793-
if (fileList != null) {
4794-
for (File item : fileList) {
4795-
newSourceName = addItemToZip(zipPrefix, item);
4796-
}
4797-
}
4798-
}
4799-
return newSourceName;
4800-
}
4801-
48024786
private void checkForZipSlip(File extractLocation, String zipEntry) throws WLSDeployArchiveIOException {
48034787
String canonicalExtractLocation = FileUtils.getCanonicalPath(extractLocation);
48044788
String canonicalZipEntry = FileUtils.getCanonicalPath(new File(extractLocation, zipEntry));

core/src/main/python/wlsdeploy/aliases/aliases.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,10 +1000,11 @@ def is_model_password_attribute(self, location, model_name):
10001000
self._raise_exception(ae, _method_name, 'WLSDPLY-19040', model_name, location.get_folder_path(),
10011001
ae.getLocalizedMessage())
10021002

1003-
def get_model_uses_path_tokens_attribute_names(self, location):
1003+
def get_model_uses_path_tokens_attribute_names(self, location, only_readable=False):
10041004
"""
10051005
Get the list of attribute names that "use path tokens" (i.e., ones whose values are file system paths).
10061006
:param location: the location
1007+
:param only_readable: If true, filter out all attributes that cannot be read (i.e., IGNORED)
10071008
:return: a list of the model attribute names
10081009
:raises: Tool type exception: if an error occurs
10091010
"""
@@ -1020,7 +1021,8 @@ def get_model_uses_path_tokens_attribute_names(self, location):
10201021

10211022
for key, value in module_folder[ATTRIBUTES].iteritems():
10221023
if USES_PATH_TOKENS in value and alias_utils.convert_boolean(value[USES_PATH_TOKENS]):
1023-
model_attribute_names.append(key)
1024+
if not (only_readable and ACCESS in value and value[ACCESS] == IGNORED):
1025+
model_attribute_names.append(key)
10241026

10251027
return model_attribute_names
10261028
except AliasException, ae:

0 commit comments

Comments
 (0)